Merge pull request #2403 from awakecoding/master
Transport, Gateway, Sockets
This commit is contained in:
commit
3f371b22ad
@ -173,6 +173,8 @@ int tfreerdp_run(freerdp* instance)
|
||||
FD_ZERO(&rfds_set);
|
||||
FD_ZERO(&wfds_set);
|
||||
|
||||
fprintf(stderr, "rcount: %d\n", rcount);
|
||||
|
||||
for (i = 0; i < rcount; i++)
|
||||
{
|
||||
fds = (int)(long)(rfds[i]);
|
||||
@ -237,7 +239,11 @@ void* tf_client_thread_proc(freerdp* instance)
|
||||
|
||||
channels = instance->context->channels;
|
||||
|
||||
freerdp_connect(instance);
|
||||
if (!freerdp_connect(instance))
|
||||
{
|
||||
WLog_ERR(TAG, "connection failure");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
@ -30,7 +30,6 @@ int xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* re
|
||||
{
|
||||
int count;
|
||||
int index;
|
||||
int status = 1;
|
||||
xfGfxSurface* surface;
|
||||
UINT16* pSurfaceIds = NULL;
|
||||
xfContext* xfc = (xfContext*) context->custom;
|
||||
|
@ -248,7 +248,7 @@ FREERDP_API BOOL freerdp_reconnect(freerdp* instance);
|
||||
FREERDP_API BOOL freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount);
|
||||
FREERDP_API BOOL freerdp_check_fds(freerdp* instance);
|
||||
|
||||
FREERDP_API DWORD freerdp_get_event_handles(rdpContext* context, HANDLE* events);
|
||||
FREERDP_API UINT32 freerdp_get_event_handles(rdpContext* context, HANDLE* events);
|
||||
FREERDP_API BOOL freerdp_check_event_handles(rdpContext* context);
|
||||
|
||||
FREERDP_API wMessageQueue* freerdp_get_message_queue(freerdp* instance, DWORD id);
|
||||
|
@ -263,12 +263,12 @@ BOOL rdp_client_connect(rdpRdp* rdp)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_NEGO);
|
||||
|
||||
if (!nego_connect(rdp->nego))
|
||||
{
|
||||
if (!freerdp_get_last_error(rdp->context))
|
||||
{
|
||||
freerdp_set_last_error(rdp->context, FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED);
|
||||
}
|
||||
|
||||
WLog_ERR(TAG, "Error: protocol security negotiation or connection failure");
|
||||
return FALSE;
|
||||
@ -281,25 +281,16 @@ BOOL rdp_client_connect(rdpRdp* rdp)
|
||||
settings->AutoLogonEnabled = TRUE;
|
||||
}
|
||||
|
||||
rdp_set_blocking_mode(rdp, FALSE);
|
||||
/* everything beyond this point is event-driven and non blocking */
|
||||
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_NEGO);
|
||||
rdp->finalize_sc_pdus = 0;
|
||||
rdp->transport->ReceiveCallback = rdp_recv_callback;
|
||||
rdp->transport->ReceiveExtra = rdp;
|
||||
transport_set_blocking_mode(rdp->transport, FALSE);
|
||||
|
||||
if (!mcs_send_connect_initial(rdp->mcs))
|
||||
if (rdp->state != CONNECTION_STATE_NLA)
|
||||
{
|
||||
if (!connectErrorCode)
|
||||
{
|
||||
connectErrorCode = MCSCONNECTINITIALERROR;
|
||||
}
|
||||
|
||||
if (!freerdp_get_last_error(rdp->context))
|
||||
{
|
||||
freerdp_set_last_error(rdp->context, FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR);
|
||||
}
|
||||
|
||||
WLog_ERR(TAG, "Error: unable to send MCS Connect Initial");
|
||||
return FALSE;
|
||||
if (!mcs_client_begin(rdp->mcs))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (rdp->state != CONNECTION_STATE_ACTIVE)
|
||||
@ -307,9 +298,7 @@ BOOL rdp_client_connect(rdpRdp* rdp)
|
||||
if (rdp_check_fds(rdp) < 0)
|
||||
{
|
||||
if (!freerdp_get_last_error(rdp->context))
|
||||
{
|
||||
freerdp_set_last_error(rdp->context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@ -648,38 +637,6 @@ end2:
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL rdp_client_connect_mcs_connect_response(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
if (!mcs_recv_connect_response(rdp->mcs, s))
|
||||
{
|
||||
WLog_ERR(TAG, "rdp_client_connect_mcs_connect_response: mcs_recv_connect_response failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!mcs_send_erect_domain_request(rdp->mcs))
|
||||
return FALSE;
|
||||
|
||||
if (!mcs_send_attach_user_request(rdp->mcs))
|
||||
return FALSE;
|
||||
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_ATTACH_USER);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL rdp_client_connect_mcs_attach_user_confirm(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
if (!mcs_recv_attach_user_confirm(rdp->mcs, s))
|
||||
return FALSE;
|
||||
|
||||
if (!mcs_send_channel_join_request(rdp->mcs, rdp->mcs->userId))
|
||||
return FALSE;
|
||||
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
UINT32 i;
|
||||
@ -925,6 +882,10 @@ int rdp_client_transition_to_state(rdpRdp* rdp, int state)
|
||||
rdp->state = CONNECTION_STATE_NEGO;
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_NLA:
|
||||
rdp->state = CONNECTION_STATE_NLA;
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_MCS_CONNECT:
|
||||
rdp->state = CONNECTION_STATE_MCS_CONNECT;
|
||||
break;
|
||||
|
@ -31,28 +31,27 @@
|
||||
|
||||
enum CONNECTION_STATE
|
||||
{
|
||||
CONNECTION_STATE_INITIAL = 0,
|
||||
CONNECTION_STATE_NEGO = 1,
|
||||
CONNECTION_STATE_MCS_CONNECT = 2,
|
||||
CONNECTION_STATE_MCS_ERECT_DOMAIN = 3,
|
||||
CONNECTION_STATE_MCS_ATTACH_USER = 4,
|
||||
CONNECTION_STATE_MCS_CHANNEL_JOIN = 5,
|
||||
CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT = 6,
|
||||
CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE = 7,
|
||||
CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT = 8,
|
||||
CONNECTION_STATE_LICENSING = 9,
|
||||
CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING = 10,
|
||||
CONNECTION_STATE_CAPABILITIES_EXCHANGE = 11,
|
||||
CONNECTION_STATE_FINALIZATION = 12,
|
||||
CONNECTION_STATE_ACTIVE = 13
|
||||
CONNECTION_STATE_INITIAL,
|
||||
CONNECTION_STATE_NEGO,
|
||||
CONNECTION_STATE_NLA,
|
||||
CONNECTION_STATE_MCS_CONNECT,
|
||||
CONNECTION_STATE_MCS_ERECT_DOMAIN,
|
||||
CONNECTION_STATE_MCS_ATTACH_USER,
|
||||
CONNECTION_STATE_MCS_CHANNEL_JOIN,
|
||||
CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT,
|
||||
CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE,
|
||||
CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT,
|
||||
CONNECTION_STATE_LICENSING,
|
||||
CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING,
|
||||
CONNECTION_STATE_CAPABILITIES_EXCHANGE,
|
||||
CONNECTION_STATE_FINALIZATION,
|
||||
CONNECTION_STATE_ACTIVE
|
||||
};
|
||||
|
||||
BOOL rdp_client_connect(rdpRdp* rdp);
|
||||
BOOL rdp_client_disconnect(rdpRdp* rdp);
|
||||
BOOL rdp_client_reconnect(rdpRdp* rdp);
|
||||
BOOL rdp_client_redirect(rdpRdp* rdp);
|
||||
BOOL rdp_client_connect_mcs_connect_response(rdpRdp* rdp, wStream* s);
|
||||
BOOL rdp_client_connect_mcs_attach_user_confirm(rdpRdp* rdp, wStream* s);
|
||||
BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s);
|
||||
BOOL rdp_client_connect_auto_detect(rdpRdp* rdp, wStream* s);
|
||||
int rdp_client_connect_license(rdpRdp* rdp, wStream* s);
|
||||
|
@ -84,17 +84,10 @@ BOOL freerdp_connect(freerdp* instance)
|
||||
|
||||
if (!status)
|
||||
{
|
||||
if (!connectErrorCode)
|
||||
{
|
||||
connectErrorCode = PREECONNECTERROR;
|
||||
}
|
||||
|
||||
if (!freerdp_get_last_error(rdp->context))
|
||||
{
|
||||
freerdp_set_last_error(instance->context, FREERDP_ERROR_PRE_CONNECT_FAILED);
|
||||
}
|
||||
|
||||
WLog_ERR(TAG, "freerdp_pre_connect failed");
|
||||
WLog_ERR(TAG, "freerdp_pre_connect failed");
|
||||
goto freerdp_connect_finally;
|
||||
}
|
||||
|
||||
@ -103,7 +96,7 @@ BOOL freerdp_connect(freerdp* instance)
|
||||
/* --authonly tests the connection without a UI */
|
||||
if (instance->settings->AuthenticationOnly)
|
||||
{
|
||||
WLog_ERR(TAG, "Authentication only, exit status %d", !status);
|
||||
WLog_ERR(TAG, "Authentication only, exit status %d", !status);
|
||||
goto freerdp_connect_finally;
|
||||
}
|
||||
|
||||
@ -122,17 +115,10 @@ BOOL freerdp_connect(freerdp* instance)
|
||||
|
||||
if (!status)
|
||||
{
|
||||
WLog_ERR(TAG, "freerdp_post_connect failed");
|
||||
|
||||
if (!connectErrorCode)
|
||||
{
|
||||
connectErrorCode = POSTCONNECTERROR;
|
||||
}
|
||||
WLog_ERR(TAG, "freerdp_post_connect failed");
|
||||
|
||||
if (!freerdp_get_last_error(rdp->context))
|
||||
{
|
||||
freerdp_set_last_error(instance->context, FREERDP_ERROR_POST_CONNECT_FAILED);
|
||||
}
|
||||
|
||||
goto freerdp_connect_finally;
|
||||
}
|
||||
@ -183,10 +169,7 @@ BOOL freerdp_connect(freerdp* instance)
|
||||
}
|
||||
|
||||
if (rdp->errorInfo == ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES)
|
||||
{
|
||||
connectErrorCode = INSUFFICIENTPRIVILEGESERROR;
|
||||
freerdp_set_last_error(instance->context, FREERDP_ERROR_INSUFFICIENT_PRIVILEGES);
|
||||
}
|
||||
|
||||
SetEvent(rdp->transport->connectedEvent);
|
||||
freerdp_connect_finally:
|
||||
@ -199,11 +182,8 @@ freerdp_connect_finally:
|
||||
|
||||
BOOL freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount)
|
||||
{
|
||||
rdpRdp* rdp;
|
||||
|
||||
rdp = instance->context->rdp;
|
||||
rdpRdp* rdp = instance->context->rdp;
|
||||
transport_get_fds(rdp->transport, rfds, rcount);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -240,9 +220,9 @@ BOOL freerdp_check_fds(freerdp* instance)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD freerdp_get_event_handles(rdpContext* context, HANDLE* events)
|
||||
UINT32 freerdp_get_event_handles(rdpContext* context, HANDLE* events)
|
||||
{
|
||||
DWORD nCount = 0;
|
||||
UINT32 nCount = 0;
|
||||
|
||||
nCount += transport_get_event_handles(context->rdp->transport, events);
|
||||
|
||||
@ -534,9 +514,64 @@ UINT32 freerdp_get_last_error(rdpContext* context)
|
||||
void freerdp_set_last_error(rdpContext* context, UINT32 lastError)
|
||||
{
|
||||
if (lastError)
|
||||
WLog_ERR(TAG, "freerdp_set_last_error 0x%04X", lastError);
|
||||
WLog_ERR(TAG, "freerdp_set_last_error 0x%04X", lastError);
|
||||
|
||||
context->LastError = lastError;
|
||||
|
||||
switch (lastError)
|
||||
{
|
||||
case FREERDP_ERROR_PRE_CONNECT_FAILED:
|
||||
connectErrorCode = PREECONNECTERROR;
|
||||
break;
|
||||
|
||||
case FREERDP_ERROR_CONNECT_UNDEFINED:
|
||||
connectErrorCode = UNDEFINEDCONNECTERROR;
|
||||
break;
|
||||
|
||||
case FREERDP_ERROR_POST_CONNECT_FAILED:
|
||||
connectErrorCode = POSTCONNECTERROR;
|
||||
break;
|
||||
|
||||
case FREERDP_ERROR_DNS_ERROR:
|
||||
connectErrorCode = DNSERROR;
|
||||
break;
|
||||
|
||||
case FREERDP_ERROR_DNS_NAME_NOT_FOUND:
|
||||
connectErrorCode = DNSNAMENOTFOUND;
|
||||
break;
|
||||
|
||||
case FREERDP_ERROR_CONNECT_FAILED:
|
||||
connectErrorCode = CONNECTERROR;
|
||||
break;
|
||||
|
||||
case FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR:
|
||||
connectErrorCode = MCSCONNECTINITIALERROR;
|
||||
break;
|
||||
|
||||
case FREERDP_ERROR_TLS_CONNECT_FAILED:
|
||||
connectErrorCode = TLSCONNECTERROR;
|
||||
break;
|
||||
|
||||
case FREERDP_ERROR_AUTHENTICATION_FAILED:
|
||||
connectErrorCode = AUTHENTICATIONERROR;
|
||||
break;
|
||||
|
||||
case FREERDP_ERROR_INSUFFICIENT_PRIVILEGES:
|
||||
connectErrorCode = INSUFFICIENTPRIVILEGESERROR;
|
||||
break;
|
||||
|
||||
case FREERDP_ERROR_CONNECT_CANCELLED:
|
||||
connectErrorCode = CANCELEDBYUSER;
|
||||
break;
|
||||
|
||||
case FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED:
|
||||
connectErrorCode = CONNECTERROR;
|
||||
break;
|
||||
|
||||
case FREERDP_ERROR_CONNECT_TRANSPORT_FAILED:
|
||||
connectErrorCode = CONNECTERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Allocator function for the rdp_freerdp structure.
|
||||
|
@ -132,7 +132,6 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, RpcChannel* channel)
|
||||
|
||||
if (!proceed)
|
||||
{
|
||||
connectErrorCode = CANCELEDBYUSER;
|
||||
freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
|
||||
return 0;
|
||||
}
|
||||
|
@ -506,6 +506,18 @@ void rpc_in_channel_free(RpcInChannel* inChannel)
|
||||
|
||||
rpc_in_channel_rpch_uninit(inChannel);
|
||||
|
||||
if (inChannel->tls)
|
||||
{
|
||||
tls_free(inChannel->tls);
|
||||
inChannel->tls = NULL;
|
||||
}
|
||||
|
||||
if (inChannel->bio)
|
||||
{
|
||||
BIO_free(inChannel->bio);
|
||||
inChannel->bio = NULL;
|
||||
}
|
||||
|
||||
free(inChannel);
|
||||
}
|
||||
|
||||
@ -645,6 +657,18 @@ void rpc_out_channel_free(RpcOutChannel* outChannel)
|
||||
|
||||
rpc_out_channel_rpch_uninit(outChannel);
|
||||
|
||||
if (outChannel->tls)
|
||||
{
|
||||
tls_free(outChannel->tls);
|
||||
outChannel->tls = NULL;
|
||||
}
|
||||
|
||||
if (outChannel->bio)
|
||||
{
|
||||
BIO_free(outChannel->bio);
|
||||
outChannel->bio = NULL;
|
||||
}
|
||||
|
||||
free(outChannel);
|
||||
}
|
||||
|
||||
@ -735,21 +759,39 @@ void rpc_virtual_connection_free(RpcVirtualConnection* connection)
|
||||
|
||||
int rpc_channel_tls_connect(RpcChannel* channel, int timeout)
|
||||
{
|
||||
rdpTcp* tcp;
|
||||
int sockfd;
|
||||
rdpTls* tls;
|
||||
int tlsStatus;
|
||||
BIO* socketBio;
|
||||
BIO* bufferedBio;
|
||||
rdpRpc* rpc = channel->rpc;
|
||||
rdpContext* context = rpc->context;
|
||||
rdpSettings* settings = context->settings;
|
||||
|
||||
tcp = channel->tcp = freerdp_tcp_new(settings);
|
||||
sockfd = freerdp_tcp_connect(settings, settings->GatewayHostname, settings->GatewayPort, timeout);
|
||||
|
||||
if (!freerdp_tcp_connect(tcp, settings->GatewayHostname, settings->GatewayPort, timeout))
|
||||
if (sockfd < 1)
|
||||
return -1;
|
||||
|
||||
if (!freerdp_tcp_set_blocking_mode(tcp, FALSE))
|
||||
socketBio = BIO_new(BIO_s_simple_socket());
|
||||
|
||||
if (!socketBio)
|
||||
return FALSE;
|
||||
|
||||
BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
|
||||
|
||||
bufferedBio = BIO_new(BIO_s_buffered_socket());
|
||||
|
||||
if (!bufferedBio)
|
||||
return FALSE;
|
||||
|
||||
bufferedBio = BIO_push(bufferedBio, socketBio);
|
||||
|
||||
if (!BIO_set_nonblock(bufferedBio, TRUE))
|
||||
return -1;
|
||||
|
||||
channel->bio = bufferedBio;
|
||||
|
||||
tls = channel->tls = tls_new(settings);
|
||||
|
||||
if (!tls)
|
||||
@ -759,7 +801,7 @@ int rpc_channel_tls_connect(RpcChannel* channel, int timeout)
|
||||
tls->port = settings->GatewayPort;
|
||||
tls->isGatewayTransport = TRUE;
|
||||
|
||||
tlsStatus = tls_connect(tls, tcp->bufferedBio);
|
||||
tlsStatus = tls_connect(tls, bufferedBio);
|
||||
|
||||
if (tlsStatus < 1)
|
||||
{
|
||||
|
@ -586,7 +586,7 @@ typedef struct rpc_client_call RpcClientCall;
|
||||
|
||||
#define RPC_CHANNEL_COMMON() \
|
||||
rdpRpc* rpc; \
|
||||
rdpTcp* tcp; \
|
||||
BIO* bio; \
|
||||
rdpTls* tls; \
|
||||
rdpNtlm* ntlm; \
|
||||
HttpContext* http; \
|
||||
|
@ -143,7 +143,6 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
|
||||
|
||||
if (!proceed)
|
||||
{
|
||||
connectErrorCode = CANCELEDBYUSER;
|
||||
freerdp_set_last_error(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
|
||||
return 0;
|
||||
}
|
||||
|
@ -280,15 +280,12 @@ int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu)
|
||||
|
||||
rpc_client_transition_to_state(rpc, RPC_CLIENT_STATE_CONTEXT_NEGOTIATED);
|
||||
|
||||
if (!TsProxyCreateTunnel(tsg, NULL, NULL, NULL, NULL))
|
||||
if (tsg_proxy_begin(tsg) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "TsProxyCreateTunnel failure");
|
||||
tsg->state = TSG_STATE_FINAL;
|
||||
WLog_ERR(TAG, "tsg_proxy_begin failure");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tsg_transition_to_state(tsg, TSG_STATE_INITIAL);
|
||||
|
||||
status = 1;
|
||||
}
|
||||
else
|
||||
@ -298,10 +295,7 @@ int rpc_client_recv_pdu(rdpRpc* rpc, RPC_PDU* pdu)
|
||||
}
|
||||
else if (rpc->State >= RPC_CLIENT_STATE_CONTEXT_NEGOTIATED)
|
||||
{
|
||||
if (tsg->state != TSG_STATE_PIPE_CREATED)
|
||||
{
|
||||
status = tsg_recv_pdu(tsg, pdu);
|
||||
}
|
||||
status = tsg_recv_pdu(tsg, pdu);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -531,13 +525,8 @@ int rpc_client_out_channel_recv(rdpRpc* rpc)
|
||||
|
||||
if (response->StatusCode == HTTP_STATUS_DENIED)
|
||||
{
|
||||
if (!connectErrorCode)
|
||||
connectErrorCode = AUTHENTICATIONERROR;
|
||||
|
||||
if (!freerdp_get_last_error(rpc->context))
|
||||
{
|
||||
freerdp_set_last_error(rpc->context, FREERDP_ERROR_AUTHENTICATION_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -53,20 +53,6 @@ enum _TSG_STATE
|
||||
};
|
||||
typedef enum _TSG_STATE TSG_STATE;
|
||||
|
||||
struct rdp_tsg
|
||||
{
|
||||
BIO* bio;
|
||||
rdpRpc* rpc;
|
||||
UINT16 Port;
|
||||
LPWSTR Hostname;
|
||||
LPWSTR MachineName;
|
||||
TSG_STATE state;
|
||||
rdpSettings* settings;
|
||||
rdpTransport* transport;
|
||||
CONTEXT_HANDLE TunnelContext;
|
||||
CONTEXT_HANDLE ChannelContext;
|
||||
};
|
||||
|
||||
typedef WCHAR* RESOURCENAME;
|
||||
|
||||
#define TsProxyCreateTunnelOpnum 1
|
||||
@ -299,8 +285,31 @@ typedef struct _TSG_PACKET
|
||||
TSG_PACKET_TYPE_UNION tsgPacket;
|
||||
} TSG_PACKET, *PTSG_PACKET;
|
||||
|
||||
BOOL TsProxyCreateTunnel(rdpTsg* tsg, PTSG_PACKET tsgPacket, PTSG_PACKET* tsgPacketResponse,
|
||||
PTUNNEL_CONTEXT_HANDLE_SERIALIZE* tunnelContext, UINT32* tunnelId);
|
||||
struct rdp_tsg
|
||||
{
|
||||
BIO* bio;
|
||||
rdpRpc* rpc;
|
||||
UINT16 Port;
|
||||
LPWSTR Hostname;
|
||||
LPWSTR MachineName;
|
||||
TSG_STATE state;
|
||||
UINT32 TunnelId;
|
||||
UINT32 ChannelId;
|
||||
BOOL reauthSequence;
|
||||
rdpSettings* settings;
|
||||
rdpTransport* transport;
|
||||
UINT64 ReauthTunnelContext;
|
||||
CONTEXT_HANDLE TunnelContext;
|
||||
CONTEXT_HANDLE ChannelContext;
|
||||
CONTEXT_HANDLE NewTunnelContext;
|
||||
CONTEXT_HANDLE NewChannelContext;
|
||||
TSG_PACKET_REAUTH packetReauth;
|
||||
TSG_PACKET_CAPABILITIES tsgCaps;
|
||||
TSG_PACKET_VERSIONCAPS packetVersionCaps;
|
||||
};
|
||||
|
||||
int tsg_proxy_begin(rdpTsg* tsg);
|
||||
int tsg_proxy_reauth(rdpTsg* tsg);
|
||||
|
||||
DWORD TsProxySendToServer(handle_t IDL_handle, BYTE pRpcMessage[], UINT32 count, UINT32* lengths);
|
||||
|
||||
@ -313,7 +322,9 @@ int tsg_write(rdpTsg* tsg, BYTE* data, UINT32 length);
|
||||
int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length);
|
||||
|
||||
int tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu);
|
||||
int tsg_check(rdpTsg* tsg);
|
||||
|
||||
int tsg_check_event_handles(rdpTsg* tsg);
|
||||
UINT32 tsg_get_event_handles(rdpTsg* tsg, HANDLE* events);
|
||||
|
||||
rdpTsg* tsg_new(rdpTransport* transport);
|
||||
void tsg_free(rdpTsg* tsg);
|
||||
|
@ -39,8 +39,6 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#else
|
||||
#define close(_fd) closesocket(_fd)
|
||||
#endif
|
||||
|
||||
#include "listener.h"
|
||||
@ -144,26 +142,20 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a
|
||||
ioctlsocket(sockfd, FIONBIO, &arg);
|
||||
#endif
|
||||
|
||||
status = bind(sockfd, ai->ai_addr, ai->ai_addrlen);
|
||||
status = _bind((SOCKET) sockfd, ai->ai_addr, ai->ai_addrlen);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WLog_ERR(TAG, "bind() failed with error: %d", (int) WSAGetLastError());
|
||||
WSACleanup();
|
||||
#else
|
||||
WLog_ERR(TAG, "bind");
|
||||
close(sockfd);
|
||||
#endif
|
||||
closesocket((SOCKET) sockfd);
|
||||
continue;
|
||||
}
|
||||
|
||||
status = listen(sockfd, 10);
|
||||
status = _listen((SOCKET) sockfd, 10);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
WLog_ERR(TAG, "listen");
|
||||
close(sockfd);
|
||||
closesocket((SOCKET) sockfd);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -203,28 +195,28 @@ static BOOL freerdp_listener_open_local(freerdp_listener* instance, const char*
|
||||
strncpy(addr.sun_path, path, sizeof(addr.sun_path));
|
||||
unlink(path);
|
||||
|
||||
status = bind(sockfd, (struct sockaddr*) &addr, sizeof(addr));
|
||||
status = _bind(sockfd, (struct sockaddr*) &addr, sizeof(addr));
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
WLog_ERR(TAG, "bind");
|
||||
close(sockfd);
|
||||
closesocket((SOCKET) sockfd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
status = listen(sockfd, 10);
|
||||
status = _listen(sockfd, 10);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
WLog_ERR(TAG, "listen");
|
||||
close(sockfd);
|
||||
closesocket((SOCKET) sockfd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
listener->sockfds[listener->num_sockfds] = sockfd;
|
||||
listener->events[listener->num_sockfds] = CreateFileDescriptorEvent(NULL, FALSE, FALSE, sockfd);
|
||||
listener->num_sockfds++;
|
||||
WLog_INFO(TAG, "Listening on socket %s.", addr.sun_path);
|
||||
WLog_INFO(TAG, "Listening on socket %s.", addr.sun_path);
|
||||
return TRUE;
|
||||
#else
|
||||
return TRUE;
|
||||
@ -239,7 +231,7 @@ static void freerdp_listener_close(freerdp_listener* instance)
|
||||
|
||||
for (i = 0; i < listener->num_sockfds; i++)
|
||||
{
|
||||
close(listener->sockfds[i]);
|
||||
closesocket((SOCKET) listener->sockfds[i]);
|
||||
CloseHandle(listener->events[i]);
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "tpdu.h"
|
||||
#include "tpkt.h"
|
||||
#include "client.h"
|
||||
#include "connection.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core")
|
||||
|
||||
@ -1049,6 +1050,23 @@ BOOL mcs_send_disconnect_provider_ultimatum(rdpMcs* mcs)
|
||||
return (status < 0) ? FALSE : TRUE;
|
||||
}
|
||||
|
||||
BOOL mcs_client_begin(rdpMcs* mcs)
|
||||
{
|
||||
rdpContext* context = mcs->transport->context;
|
||||
|
||||
if (!mcs_send_connect_initial(mcs))
|
||||
{
|
||||
if (!freerdp_get_last_error(context))
|
||||
freerdp_set_last_error(context, FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR);
|
||||
|
||||
WLog_ERR(TAG, "Error: unable to send MCS Connect Initial");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rdp_client_transition_to_state(context->rdp, CONNECTION_STATE_MCS_CONNECT);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate new MCS module.
|
||||
* @param transport transport
|
||||
|
@ -186,6 +186,8 @@ BOOL mcs_send_disconnect_provider_ultimatum(rdpMcs* mcs);
|
||||
BOOL mcs_read_domain_mcspdu_header(wStream* s, enum DomainMCSPDU* domainMCSPDU, UINT16* length);
|
||||
void mcs_write_domain_mcspdu_header(wStream* s, enum DomainMCSPDU domainMCSPDU, UINT16 length, BYTE options);
|
||||
|
||||
BOOL mcs_client_begin(rdpMcs* mcs);
|
||||
|
||||
rdpMcs* mcs_new(rdpTransport* transport);
|
||||
void mcs_free(rdpMcs* mcs);
|
||||
|
||||
|
@ -1033,8 +1033,6 @@ void nego_init(rdpNego* nego)
|
||||
{
|
||||
nego->state = NEGO_STATE_INITIAL;
|
||||
nego->RequestedProtocols = PROTOCOL_RDP;
|
||||
nego->transport->ReceiveCallback = nego_recv;
|
||||
nego->transport->ReceiveExtra = (void*) nego;
|
||||
nego->CookieMaxLength = DEFAULT_COOKIE_MAX_LENGTH;
|
||||
nego->sendNegoData = FALSE;
|
||||
nego->flags = 0;
|
||||
@ -1049,11 +1047,12 @@ void nego_init(rdpNego* nego)
|
||||
rdpNego* nego_new(rdpTransport* transport)
|
||||
{
|
||||
rdpNego* nego = (rdpNego*) calloc(1, sizeof(rdpNego));
|
||||
|
||||
if (!nego)
|
||||
return NULL;
|
||||
|
||||
|
||||
nego->transport = transport;
|
||||
|
||||
nego_init(nego);
|
||||
|
||||
return nego;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -17,10 +17,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CORE_CREDSSP_H
|
||||
#define FREERDP_CORE_CREDSSP_H
|
||||
#ifndef FREERDP_CORE_NLA_H
|
||||
#define FREERDP_CORE_NLA_H
|
||||
|
||||
typedef struct rdp_credssp rdpCredssp;
|
||||
typedef struct rdp_nla rdpNla;
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
@ -35,32 +35,60 @@ typedef struct rdp_credssp rdpCredssp;
|
||||
|
||||
#include "transport.h"
|
||||
|
||||
struct rdp_credssp
|
||||
enum _NLA_STATE
|
||||
{
|
||||
NLA_STATE_INITIAL,
|
||||
NLA_STATE_NEGO_TOKEN,
|
||||
NLA_STATE_PUB_KEY_AUTH,
|
||||
NLA_STATE_AUTH_INFO,
|
||||
NLA_STATE_FINAL
|
||||
};
|
||||
typedef enum _NLA_STATE NLA_STATE;
|
||||
|
||||
struct rdp_nla
|
||||
{
|
||||
BOOL server;
|
||||
int send_seq_num;
|
||||
int recv_seq_num;
|
||||
NLA_STATE state;
|
||||
int sendSeqNum;
|
||||
int recvSeqNum;
|
||||
freerdp* instance;
|
||||
CtxtHandle context;
|
||||
LPTSTR SspiModule;
|
||||
rdpSettings* settings;
|
||||
rdpTransport* transport;
|
||||
UINT32 cbMaxToken;
|
||||
ULONG fContextReq;
|
||||
ULONG pfContextAttr;
|
||||
BOOL haveContext;
|
||||
BOOL haveInputBuffer;
|
||||
BOOL havePubKeyAuth;
|
||||
SECURITY_STATUS status;
|
||||
CredHandle credentials;
|
||||
TimeStamp expiration;
|
||||
PSecPkgInfo pPackageInfo;
|
||||
SecBuffer inputBuffer;
|
||||
SecBuffer outputBuffer;
|
||||
SecBufferDesc inputBufferDesc;
|
||||
SecBufferDesc outputBufferDesc;
|
||||
SecBuffer negoToken;
|
||||
SecBuffer pubKeyAuth;
|
||||
SecBuffer authInfo;
|
||||
SecBuffer PublicKey;
|
||||
SecBuffer ts_credentials;
|
||||
CryptoRc4 rc4_seal_state;
|
||||
SecBuffer tsCredentials;
|
||||
CryptoRc4 rc4SealState;
|
||||
LPTSTR ServicePrincipalName;
|
||||
SEC_WINNT_AUTH_IDENTITY identity;
|
||||
PSecurityFunctionTable table;
|
||||
SecPkgContext_Sizes ContextSizes;
|
||||
};
|
||||
|
||||
int credssp_authenticate(rdpCredssp* credssp);
|
||||
LPTSTR credssp_make_spn(const char* ServiceClass, const char* hostname);
|
||||
int nla_authenticate(rdpNla* nla);
|
||||
LPTSTR nla_make_spn(const char* ServiceClass, const char* hostname);
|
||||
|
||||
rdpCredssp* credssp_new(freerdp* instance, rdpTransport* transport, rdpSettings* settings);
|
||||
void credssp_free(rdpCredssp* credssp);
|
||||
int nla_client_begin(rdpNla* nla);
|
||||
int nla_recv_pdu(rdpNla* nla, wStream* s);
|
||||
|
||||
#endif /* FREERDP_CORE_CREDSSP_H */
|
||||
rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* settings);
|
||||
void nla_free(rdpNla* nla);
|
||||
|
||||
#endif /* FREERDP_CORE_NLA_H */
|
||||
|
@ -229,7 +229,9 @@ static BOOL freerdp_peer_initialize(freerdp_peer* client)
|
||||
|
||||
static BOOL freerdp_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount)
|
||||
{
|
||||
rfds[*rcount] = (void*)(long)(client->context->rdp->transport->TcpIn->sockfd);
|
||||
rdpTransport* transport = client->context->rdp->transport;
|
||||
|
||||
rfds[*rcount] = (void*)(long)(BIO_get_fd(transport->frontBio, NULL));
|
||||
(*rcount)++;
|
||||
|
||||
return TRUE;
|
||||
@ -237,7 +239,12 @@ static BOOL freerdp_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount)
|
||||
|
||||
static HANDLE freerdp_peer_get_event_handle(freerdp_peer* client)
|
||||
{
|
||||
return client->context->rdp->transport->TcpIn->event;
|
||||
HANDLE hEvent = NULL;
|
||||
rdpTransport* transport = client->context->rdp->transport;
|
||||
|
||||
BIO_get_event(transport->frontBio, &hEvent);
|
||||
|
||||
return hEvent;
|
||||
}
|
||||
|
||||
static BOOL freerdp_peer_check_fds(freerdp_peer* peer)
|
||||
@ -453,10 +460,10 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
|
||||
if (rdp->nego->SelectedProtocol & PROTOCOL_NLA)
|
||||
{
|
||||
sspi_CopyAuthIdentity(&client->identity, &(rdp->nego->transport->credssp->identity));
|
||||
sspi_CopyAuthIdentity(&client->identity, &(rdp->nego->transport->nla->identity));
|
||||
IFCALLRET(client->Logon, client->authenticated, client, &client->identity, TRUE);
|
||||
credssp_free(rdp->nego->transport->credssp);
|
||||
rdp->nego->transport->credssp = NULL;
|
||||
nla_free(rdp->nego->transport->nla);
|
||||
rdp->nego->transport->nla = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -590,7 +597,8 @@ static BOOL freerdp_peer_close(freerdp_peer* client)
|
||||
|
||||
static void freerdp_peer_disconnect(freerdp_peer* client)
|
||||
{
|
||||
transport_disconnect(client->context->rdp->transport);
|
||||
rdpTransport* transport = client->context->rdp->transport;
|
||||
transport_disconnect(transport);
|
||||
}
|
||||
|
||||
static int freerdp_peer_send_channel_data(freerdp_peer* client, UINT16 channelId, BYTE* data, int size)
|
||||
@ -600,14 +608,14 @@ static int freerdp_peer_send_channel_data(freerdp_peer* client, UINT16 channelId
|
||||
|
||||
static BOOL freerdp_peer_is_write_blocked(freerdp_peer* peer)
|
||||
{
|
||||
return tranport_is_write_blocked(peer->context->rdp->transport);
|
||||
rdpTransport* transport = peer->context->rdp->transport;
|
||||
return transport_is_write_blocked(transport);
|
||||
}
|
||||
|
||||
static int freerdp_peer_drain_output_buffer(freerdp_peer* peer)
|
||||
{
|
||||
rdpTransport* transport = peer->context->rdp->transport;
|
||||
|
||||
return tranport_drain_output_buffer(transport);
|
||||
return transport_drain_output_buffer(transport);
|
||||
}
|
||||
|
||||
void freerdp_peer_context_new(freerdp_peer* client)
|
||||
|
@ -361,7 +361,7 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId)
|
||||
rdp_set_error_info(rdp, ERRINFO_RPC_INITIATED_DISCONNECT);
|
||||
}
|
||||
|
||||
WLog_ERR(TAG, "DisconnectProviderUltimatum: reason: %d", reason);
|
||||
WLog_ERR(TAG, "DisconnectProviderUltimatum: reason: %d", reason);
|
||||
rdp->disconnect = TRUE;
|
||||
|
||||
EventArgsInit(&e, "freerdp");
|
||||
@ -748,7 +748,7 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
|
||||
|
||||
if (Stream_GetRemainingLength(s) < (size_t) SrcSize)
|
||||
{
|
||||
WLog_ERR(TAG, "bulk_decompress: not enough bytes for compressedLength %d", compressedLength);
|
||||
WLog_ERR(TAG, "bulk_decompress: not enough bytes for compressedLength %d", compressedLength);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -763,7 +763,7 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_ERR(TAG, "bulk_decompress() failed");
|
||||
WLog_ERR(TAG, "bulk_decompress() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -970,13 +970,13 @@ BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, int length, UINT16 securityFlags)
|
||||
|
||||
if (!security_fips_decrypt(Stream_Pointer(s), length, rdp))
|
||||
{
|
||||
WLog_ERR(TAG, "FATAL: cannot decrypt");
|
||||
WLog_ERR(TAG, "FATAL: cannot decrypt");
|
||||
return FALSE; /* TODO */
|
||||
}
|
||||
|
||||
if (!security_fips_check_signature(Stream_Pointer(s), length - pad, sig, rdp))
|
||||
{
|
||||
WLog_ERR(TAG, "FATAL: invalid packet signature");
|
||||
WLog_ERR(TAG, "FATAL: invalid packet signature");
|
||||
return FALSE; /* TODO */
|
||||
}
|
||||
|
||||
@ -1000,7 +1000,7 @@ BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, int length, UINT16 securityFlags)
|
||||
|
||||
if (memcmp(wmac, cmac, sizeof(wmac)) != 0)
|
||||
{
|
||||
WLog_ERR(TAG, "WARNING: invalid packet signature");
|
||||
WLog_ERR(TAG, "WARNING: invalid packet signature");
|
||||
/*
|
||||
* Because Standard RDP Security is totally broken,
|
||||
* and cannot protect against MITM, don't treat signature
|
||||
@ -1032,7 +1032,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
|
||||
|
||||
if (!rdp_read_header(rdp, s, &length, &channelId))
|
||||
{
|
||||
WLog_ERR(TAG, "Incorrect RDP header.");
|
||||
WLog_ERR(TAG, "Incorrect RDP header.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1053,7 +1053,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
if (!rdp_decrypt(rdp, s, length - 4, securityFlags))
|
||||
{
|
||||
WLog_ERR(TAG, "rdp_decrypt failed");
|
||||
WLog_ERR(TAG, "rdp_decrypt failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -1088,7 +1088,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
|
||||
case PDU_TYPE_DATA:
|
||||
if (rdp_recv_data_pdu(rdp, s) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "rdp_recv_data_pdu failed");
|
||||
WLog_ERR(TAG, "rdp_recv_data_pdu failed");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
@ -1108,7 +1108,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "incorrect PDU type: 0x%04X", pduType);
|
||||
WLog_ERR(TAG, "incorrect PDU type: 0x%04X", pduType);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1140,7 +1140,7 @@ static int rdp_recv_fastpath_pdu(rdpRdp* rdp, wStream* s)
|
||||
|
||||
if ((length == 0) || (length > Stream_GetRemainingLength(s)))
|
||||
{
|
||||
WLog_ERR(TAG, "incorrect FastPath PDU header length %d", length);
|
||||
WLog_ERR(TAG, "incorrect FastPath PDU header length %d", length);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1168,7 +1168,7 @@ static int rdp_recv_pdu(rdpRdp* rdp, wStream* s)
|
||||
return rdp_recv_fastpath_pdu(rdp, s);
|
||||
}
|
||||
|
||||
static int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
{
|
||||
int status = 0;
|
||||
rdpRdp* rdp = (rdpRdp*) extra;
|
||||
@ -1179,8 +1179,7 @@ static int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
* enters the active state, an auto-detect PDU can be received
|
||||
* on the MCS message channel.
|
||||
*/
|
||||
if ((rdp->state > CONNECTION_STATE_MCS_CHANNEL_JOIN) &&
|
||||
(rdp->state < CONNECTION_STATE_ACTIVE))
|
||||
if ((rdp->state > CONNECTION_STATE_MCS_CHANNEL_JOIN) && (rdp->state < CONNECTION_STATE_ACTIVE))
|
||||
{
|
||||
if (rdp_client_connect_auto_detect(rdp, s))
|
||||
return 0;
|
||||
@ -1188,14 +1187,59 @@ static int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
|
||||
switch (rdp->state)
|
||||
{
|
||||
case CONNECTION_STATE_NEGO:
|
||||
if (!rdp_client_connect_mcs_connect_response(rdp, s))
|
||||
status = -1;
|
||||
case CONNECTION_STATE_NLA:
|
||||
if (nla_recv_pdu(rdp->nla, s) < 1)
|
||||
return -1;
|
||||
|
||||
if (rdp->nla->state == NLA_STATE_AUTH_INFO)
|
||||
{
|
||||
transport_set_nla_mode(rdp->transport, FALSE);
|
||||
|
||||
nla_free(rdp->nla);
|
||||
rdp->nla = NULL;
|
||||
|
||||
if (!mcs_client_begin(rdp->mcs))
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_MCS_CONNECT:
|
||||
if (!mcs_recv_connect_response(rdp->mcs, s))
|
||||
{
|
||||
WLog_ERR(TAG, "mcs_recv_connect_response failure");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!mcs_send_erect_domain_request(rdp->mcs))
|
||||
{
|
||||
WLog_ERR(TAG, "mcs_send_erect_domain_request failure");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!mcs_send_attach_user_request(rdp->mcs))
|
||||
{
|
||||
WLog_ERR(TAG, "mcs_send_attach_user_request failure");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_ATTACH_USER);
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_MCS_ATTACH_USER:
|
||||
if (!rdp_client_connect_mcs_attach_user_confirm(rdp, s))
|
||||
status = -1;
|
||||
if (!mcs_recv_attach_user_confirm(rdp->mcs, s))
|
||||
{
|
||||
WLog_ERR(TAG, "mcs_recv_attach_user_confirm failure");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!mcs_send_channel_join_request(rdp->mcs, rdp->mcs->userId))
|
||||
{
|
||||
WLog_ERR(TAG, "mcs_send_channel_join_request failure");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN);
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_MCS_CHANNEL_JOIN:
|
||||
@ -1226,7 +1270,7 @@ static int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "Invalid state %d", rdp->state);
|
||||
WLog_ERR(TAG, "Invalid state %d", rdp->state);
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
@ -1256,18 +1300,6 @@ BOOL rdp_send_error_info(rdpRdp* rdp)
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set non-blocking mode information.
|
||||
* @param rdp RDP module
|
||||
* @param blocking blocking mode
|
||||
*/
|
||||
void rdp_set_blocking_mode(rdpRdp* rdp, BOOL blocking)
|
||||
{
|
||||
rdp->transport->ReceiveCallback = rdp_recv_callback;
|
||||
rdp->transport->ReceiveExtra = rdp;
|
||||
transport_set_blocking_mode(rdp->transport, blocking);
|
||||
}
|
||||
|
||||
int rdp_check_fds(rdpRdp* rdp)
|
||||
{
|
||||
int status;
|
||||
@ -1277,7 +1309,7 @@ int rdp_check_fds(rdpRdp* rdp)
|
||||
{
|
||||
rdpTsg* tsg = transport->tsg;
|
||||
|
||||
status = tsg_check(tsg);
|
||||
status = tsg_check_event_handles(tsg);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
@ -1513,6 +1545,7 @@ void rdp_free(rdpRdp* rdp)
|
||||
fastpath_free(rdp->fastpath);
|
||||
nego_free(rdp->nego);
|
||||
mcs_free(rdp->mcs);
|
||||
nla_free(rdp->nla);
|
||||
redirection_free(rdp->redirection);
|
||||
autodetect_free(rdp->autodetect);
|
||||
heartbeat_free(rdp->heartbeat);
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "nla.h"
|
||||
#include "mcs.h"
|
||||
#include "tpkt.h"
|
||||
#include "bulk.h"
|
||||
@ -132,6 +133,7 @@ struct rdp_rdp
|
||||
int state;
|
||||
freerdp* instance;
|
||||
rdpContext* context;
|
||||
rdpNla* nla;
|
||||
rdpMcs* mcs;
|
||||
rdpNego* nego;
|
||||
rdpBulk* bulk;
|
||||
@ -213,7 +215,8 @@ int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s);
|
||||
|
||||
void rdp_read_flow_control_pdu(wStream* s, UINT16* type);
|
||||
|
||||
void rdp_set_blocking_mode(rdpRdp* rdp, BOOL blocking);
|
||||
int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra);
|
||||
|
||||
int rdp_check_fds(rdpRdp* rdp);
|
||||
|
||||
rdpRdp* rdp_new(rdpContext* context);
|
||||
|
@ -22,9 +22,6 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@ -93,7 +90,6 @@
|
||||
|
||||
struct _WINPR_BIO_SIMPLE_SOCKET
|
||||
{
|
||||
BOOL win32;
|
||||
SOCKET socket;
|
||||
HANDLE hEvent;
|
||||
};
|
||||
@ -107,8 +103,9 @@ static void transport_bio_simple_check_reset_event(BIO* bio)
|
||||
u_long nbytes = 0;
|
||||
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
|
||||
|
||||
if (!ptr->win32)
|
||||
return;
|
||||
#ifndef _WIN32
|
||||
return;
|
||||
#endif
|
||||
|
||||
_ioctlsocket(ptr->socket, FIONREAD, &nbytes);
|
||||
|
||||
@ -252,6 +249,78 @@ static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
else if (cmd == BIO_C_WAIT_READ)
|
||||
{
|
||||
int timeout = (int) arg1;
|
||||
int sockfd = (int) ptr->socket;
|
||||
#ifdef HAVE_POLL_H
|
||||
struct pollfd pollset;
|
||||
|
||||
pollset.fd = sockfd;
|
||||
pollset.events = POLLIN;
|
||||
pollset.revents = 0;
|
||||
|
||||
do
|
||||
{
|
||||
status = poll(&pollset, 1, timeout);
|
||||
}
|
||||
while ((status < 0) && (errno == EINTR));
|
||||
#else
|
||||
fd_set rset;
|
||||
struct timeval tv;
|
||||
|
||||
FD_ZERO(&rset);
|
||||
FD_SET(sockfd, &rset);
|
||||
|
||||
if (timeout)
|
||||
{
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
status = select(sockfd + 1, &rset, NULL, NULL, timeout ? &tv : NULL);
|
||||
}
|
||||
while ((status < 0) && (errno == EINTR));
|
||||
#endif
|
||||
}
|
||||
else if (cmd == BIO_C_WAIT_WRITE)
|
||||
{
|
||||
int timeout = (int) arg1;
|
||||
int sockfd = (int) ptr->socket;
|
||||
#ifdef HAVE_POLL_H
|
||||
struct pollfd pollset;
|
||||
|
||||
pollset.fd = sockfd;
|
||||
pollset.events = POLLOUT;
|
||||
pollset.revents = 0;
|
||||
|
||||
do
|
||||
{
|
||||
status = poll(&pollset, 1, timeout);
|
||||
}
|
||||
while ((status < 0) && (errno == EINTR));
|
||||
#else
|
||||
fd_set rset;
|
||||
struct timeval tv;
|
||||
|
||||
FD_ZERO(&rset);
|
||||
FD_SET(sockfd, &rset);
|
||||
|
||||
if (timeout)
|
||||
{
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
status = select(sockfd + 1, NULL, &rset, NULL, timeout ? &tv : NULL);
|
||||
}
|
||||
while ((status < 0) && (errno == EINTR));
|
||||
#endif
|
||||
}
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
@ -308,8 +377,7 @@ static int transport_bio_simple_init(BIO* bio, SOCKET socket, int shutdown)
|
||||
bio->flags = BIO_FLAGS_SHOULD_RETRY;
|
||||
bio->init = 1;
|
||||
|
||||
if (ptr->win32)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
ptr->hEvent = WSACreateEvent(); /* creates a manual reset event */
|
||||
|
||||
if (!ptr->hEvent)
|
||||
@ -317,14 +385,12 @@ static int transport_bio_simple_init(BIO* bio, SOCKET socket, int shutdown)
|
||||
|
||||
/* WSAEventSelect automatically sets the socket in non-blocking mode */
|
||||
WSAEventSelect(ptr->socket, ptr->hEvent, FD_READ | FD_CLOSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
#else
|
||||
ptr->hEvent = CreateFileDescriptorEvent(NULL, FALSE, FALSE, (int) ptr->socket);
|
||||
|
||||
if (!ptr->hEvent)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -370,10 +436,6 @@ static int transport_bio_simple_new(BIO* bio)
|
||||
|
||||
bio->ptr = ptr;
|
||||
|
||||
#ifdef _WIN32
|
||||
ptr->win32 = TRUE;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -414,6 +476,16 @@ BIO_METHOD* BIO_s_simple_socket(void)
|
||||
|
||||
/* Buffered Socket BIO */
|
||||
|
||||
struct _WINPR_BIO_BUFFERED_SOCKET
|
||||
{
|
||||
BIO* socketBio;
|
||||
BIO* bufferedBio;
|
||||
BOOL readBlocked;
|
||||
BOOL writeBlocked;
|
||||
RingBuffer xmitBuffer;
|
||||
};
|
||||
typedef struct _WINPR_BIO_BUFFERED_SOCKET WINPR_BIO_BUFFERED_SOCKET;
|
||||
|
||||
long transport_bio_buffered_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret)
|
||||
{
|
||||
return 1;
|
||||
@ -421,26 +493,28 @@ long transport_bio_buffered_callback(BIO* bio, int mode, const char* argp, int a
|
||||
|
||||
static int transport_bio_buffered_write(BIO* bio, const char* buf, int num)
|
||||
{
|
||||
int status, ret;
|
||||
rdpTcp* tcp = (rdpTcp*) bio->ptr;
|
||||
int nchunks, committedBytes, i;
|
||||
int i, ret;
|
||||
int status;
|
||||
int nchunks;
|
||||
int committedBytes;
|
||||
DataChunk chunks[2];
|
||||
WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*) bio->ptr;
|
||||
|
||||
ret = num;
|
||||
tcp->writeBlocked = FALSE;
|
||||
ptr->writeBlocked = FALSE;
|
||||
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
|
||||
|
||||
/* we directly append extra bytes in the xmit buffer, this could be prevented
|
||||
* but for now it makes the code more simple.
|
||||
*/
|
||||
if (buf && num && !ringbuffer_write(&tcp->xmitBuffer, (const BYTE*) buf, num))
|
||||
if (buf && num && !ringbuffer_write(&ptr->xmitBuffer, (const BYTE*) buf, num))
|
||||
{
|
||||
WLog_ERR(TAG, "an error occured when writing(toWrite=%d)", num);
|
||||
WLog_ERR(TAG, "an error occured when writing (num: %d)", num);
|
||||
return -1;
|
||||
}
|
||||
|
||||
committedBytes = 0;
|
||||
nchunks = ringbuffer_peek(&tcp->xmitBuffer, chunks, ringbuffer_used(&tcp->xmitBuffer));
|
||||
nchunks = ringbuffer_peek(&ptr->xmitBuffer, chunks, ringbuffer_used(&ptr->xmitBuffer));
|
||||
|
||||
for (i = 0; i < nchunks; i++)
|
||||
{
|
||||
@ -460,7 +534,7 @@ static int transport_bio_buffered_write(BIO* bio, const char* buf, int num)
|
||||
if (BIO_should_write(bio->next_bio))
|
||||
{
|
||||
BIO_set_flags(bio, BIO_FLAGS_WRITE);
|
||||
tcp->writeBlocked = TRUE;
|
||||
ptr->writeBlocked = TRUE;
|
||||
goto out; /* EWOULDBLOCK */
|
||||
}
|
||||
}
|
||||
@ -472,16 +546,17 @@ static int transport_bio_buffered_write(BIO* bio, const char* buf, int num)
|
||||
}
|
||||
|
||||
out:
|
||||
ringbuffer_commit_read_bytes(&tcp->xmitBuffer, committedBytes);
|
||||
ringbuffer_commit_read_bytes(&ptr->xmitBuffer, committedBytes);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int transport_bio_buffered_read(BIO* bio, char* buf, int size)
|
||||
{
|
||||
int status;
|
||||
rdpTcp* tcp = (rdpTcp*) bio->ptr;
|
||||
WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*) bio->ptr;
|
||||
|
||||
tcp->readBlocked = FALSE;
|
||||
ptr->readBlocked = FALSE;
|
||||
BIO_clear_flags(bio, BIO_FLAGS_READ);
|
||||
|
||||
status = BIO_read(bio->next_bio, buf, size);
|
||||
@ -499,7 +574,7 @@ static int transport_bio_buffered_read(BIO* bio, char* buf, int size)
|
||||
if (BIO_should_read(bio->next_bio))
|
||||
{
|
||||
BIO_set_flags(bio, BIO_FLAGS_READ);
|
||||
tcp->readBlocked = TRUE;
|
||||
ptr->readBlocked = TRUE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@ -520,37 +595,78 @@ static int transport_bio_buffered_gets(BIO* bio, char* str, int size)
|
||||
|
||||
static long transport_bio_buffered_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
|
||||
{
|
||||
rdpTcp* tcp = (rdpTcp*) bio->ptr;
|
||||
int status = -1;
|
||||
WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*) bio->ptr;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case BIO_CTRL_FLUSH:
|
||||
return 1;
|
||||
if (!ringbuffer_used(&ptr->xmitBuffer))
|
||||
status = 1;
|
||||
else
|
||||
status = (transport_bio_buffered_write(bio, NULL, 0) >= 0) ? 1 : -1;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_WPENDING:
|
||||
return ringbuffer_used(&tcp->xmitBuffer);
|
||||
status = ringbuffer_used(&ptr->xmitBuffer);
|
||||
break;
|
||||
|
||||
case BIO_CTRL_PENDING:
|
||||
return 0;
|
||||
status = 0;
|
||||
break;
|
||||
|
||||
case BIO_C_READ_BLOCKED:
|
||||
status = (int) ptr->readBlocked;
|
||||
break;
|
||||
|
||||
case BIO_C_WRITE_BLOCKED:
|
||||
status = (int) ptr->writeBlocked;
|
||||
break;
|
||||
|
||||
default:
|
||||
return BIO_ctrl(bio->next_bio, cmd, arg1, arg2);
|
||||
status = BIO_ctrl(bio->next_bio, cmd, arg1, arg2);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return status;
|
||||
}
|
||||
|
||||
static int transport_bio_buffered_new(BIO* bio)
|
||||
{
|
||||
WINPR_BIO_BUFFERED_SOCKET* ptr;
|
||||
|
||||
bio->init = 1;
|
||||
bio->num = 0;
|
||||
bio->ptr = NULL;
|
||||
bio->flags = BIO_FLAGS_SHOULD_RETRY;
|
||||
|
||||
ptr = (WINPR_BIO_BUFFERED_SOCKET*) calloc(1, sizeof(WINPR_BIO_BUFFERED_SOCKET));
|
||||
|
||||
if (!ptr)
|
||||
return -1;
|
||||
|
||||
bio->ptr = (void*) ptr;
|
||||
|
||||
if (!ringbuffer_init(&ptr->xmitBuffer, 0x10000))
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int transport_bio_buffered_free(BIO* bio)
|
||||
{
|
||||
WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*) bio->ptr;
|
||||
|
||||
if (ptr->socketBio)
|
||||
{
|
||||
BIO_free(ptr->socketBio);
|
||||
ptr->socketBio = NULL;
|
||||
}
|
||||
|
||||
ringbuffer_destroy(&ptr->xmitBuffer);
|
||||
|
||||
free(ptr);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -573,43 +689,27 @@ BIO_METHOD* BIO_s_buffered_socket(void)
|
||||
return &transport_bio_buffered_socket_methods;
|
||||
}
|
||||
|
||||
BOOL transport_bio_buffered_drain(BIO *bio)
|
||||
{
|
||||
int status;
|
||||
rdpTcp* tcp = (rdpTcp*) bio->ptr;
|
||||
|
||||
if (!ringbuffer_used(&tcp->xmitBuffer))
|
||||
return 1;
|
||||
|
||||
status = transport_bio_buffered_write(bio, NULL, 0);
|
||||
|
||||
return status >= 0;
|
||||
}
|
||||
|
||||
void freerdp_tcp_get_ip_address(rdpTcp* tcp)
|
||||
char* freerdp_tcp_get_ip_address(int sockfd)
|
||||
{
|
||||
BYTE* ip;
|
||||
socklen_t length;
|
||||
char ipAddress[32];
|
||||
struct sockaddr_in sockaddr;
|
||||
|
||||
length = sizeof(sockaddr);
|
||||
ZeroMemory(&sockaddr, length);
|
||||
|
||||
if (getsockname(tcp->sockfd, (struct sockaddr*) &sockaddr, &length) == 0)
|
||||
if (getsockname(sockfd, (struct sockaddr*) &sockaddr, &length) == 0)
|
||||
{
|
||||
ip = (BYTE*) (&sockaddr.sin_addr);
|
||||
sprintf_s(tcp->ip_address, sizeof(tcp->ip_address),
|
||||
"%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
|
||||
sprintf_s(ipAddress, sizeof(ipAddress), "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(tcp->ip_address, "127.0.0.1");
|
||||
strcpy(ipAddress, "127.0.0.1");
|
||||
}
|
||||
|
||||
tcp->settings->IPv6Enabled = 0;
|
||||
|
||||
free(tcp->settings->ClientAddress);
|
||||
tcp->settings->ClientAddress = _strdup(tcp->ip_address);
|
||||
return _strdup(ipAddress);
|
||||
}
|
||||
|
||||
int freerdp_uds_connect(const char* path)
|
||||
@ -913,57 +1013,86 @@ int freerdp_tcp_connect_multi(char** hostnames, int count, int port, int timeout
|
||||
|
||||
#endif
|
||||
|
||||
BOOL freerdp_tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout)
|
||||
BOOL freerdp_tcp_set_keep_alive_mode(int sockfd)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
UINT32 optval;
|
||||
socklen_t optlen;
|
||||
|
||||
optval = 1;
|
||||
optlen = sizeof(optval);
|
||||
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (void*) &optval, optlen) < 0)
|
||||
{
|
||||
WLog_WARN(TAG, "setsockopt() SOL_SOCKET, SO_KEEPALIVE");
|
||||
}
|
||||
|
||||
#ifdef TCP_KEEPIDLE
|
||||
optval = 5;
|
||||
optlen = sizeof(optval);
|
||||
|
||||
if (setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, (void*) &optval, optlen) < 0)
|
||||
{
|
||||
WLog_WARN(TAG, "setsockopt() IPPROTO_TCP, TCP_KEEPIDLE");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TCP_KEEPCNT
|
||||
optval = 3;
|
||||
optlen = sizeof(optval);
|
||||
|
||||
if (setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, (void*) &optval, optlen) < 0)
|
||||
{
|
||||
WLog_WARN(TAG, "setsockopt() SOL_TCP, TCP_KEEPCNT");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TCP_KEEPINTVL
|
||||
optval = 2;
|
||||
optlen = sizeof(optval);
|
||||
|
||||
if (setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, (void*) &optval, optlen) < 0)
|
||||
{
|
||||
WLog_WARN(TAG, "setsockopt() SOL_TCP, TCP_KEEPINTVL");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__MACOSX__) || defined(__IOS__)
|
||||
optval = 1;
|
||||
optlen = sizeof(optval);
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void*) &optval, optlen) < 0)
|
||||
{
|
||||
WLog_WARN(TAG, "setsockopt() SOL_SOCKET, SO_NOSIGPIPE");
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int freerdp_tcp_connect(rdpSettings* settings, const char* hostname, int port, int timeout)
|
||||
{
|
||||
int status;
|
||||
UINT32 option_value;
|
||||
socklen_t option_len;
|
||||
rdpSettings* settings = tcp->settings;
|
||||
int sockfd;
|
||||
UINT32 optval;
|
||||
socklen_t optlen;
|
||||
BOOL ipcSocket = FALSE;
|
||||
|
||||
if (!hostname)
|
||||
return FALSE;
|
||||
return -1;
|
||||
|
||||
if (hostname[0] == '/')
|
||||
tcp->ipcSocket = TRUE;
|
||||
ipcSocket = TRUE;
|
||||
|
||||
if (tcp->ipcSocket)
|
||||
if (ipcSocket)
|
||||
{
|
||||
tcp->sockfd = freerdp_uds_connect(hostname);
|
||||
sockfd = freerdp_uds_connect(hostname);
|
||||
|
||||
if (tcp->sockfd < 0)
|
||||
return FALSE;
|
||||
|
||||
tcp->socketBio = BIO_new(BIO_s_simple_socket());
|
||||
|
||||
if (!tcp->socketBio)
|
||||
return FALSE;
|
||||
|
||||
BIO_set_fd(tcp->socketBio, tcp->sockfd, BIO_CLOSE);
|
||||
if (sockfd < 0)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef NO_IPV6
|
||||
tcp->socketBio = BIO_new(BIO_s_connect());
|
||||
|
||||
if (!tcp->socketBio)
|
||||
return FALSE;
|
||||
|
||||
if (BIO_set_conn_hostname(tcp->socketBio, hostname) < 0 || BIO_set_conn_int_port(tcp->socketBio, &port) < 0)
|
||||
return FALSE;
|
||||
|
||||
BIO_set_nbio(tcp->socketBio, 1);
|
||||
|
||||
status = BIO_do_connect(tcp->socketBio);
|
||||
|
||||
if ((status <= 0) && !BIO_should_retry(tcp->socketBio))
|
||||
return FALSE;
|
||||
|
||||
tcp->sockfd = BIO_get_fd(tcp->socketBio, NULL);
|
||||
|
||||
if (tcp->sockfd < 0)
|
||||
return FALSE;
|
||||
#else /* NO_IPV6 */
|
||||
tcp->sockfd = -1;
|
||||
sockfd = -1;
|
||||
|
||||
if (!settings->GatewayEnabled)
|
||||
{
|
||||
@ -972,7 +1101,7 @@ BOOL freerdp_tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeou
|
||||
if (settings->TargetNetAddressCount > 0)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
tcp->sockfd = freerdp_tcp_connect_multi(settings->TargetNetAddresses,
|
||||
sockfd = freerdp_tcp_connect_multi(settings->TargetNetAddresses,
|
||||
settings->TargetNetAddressCount, port, timeout);
|
||||
#else
|
||||
hostname = settings->TargetNetAddresses[0];
|
||||
@ -981,7 +1110,7 @@ BOOL freerdp_tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeou
|
||||
}
|
||||
}
|
||||
|
||||
if (tcp->sockfd <= 0)
|
||||
if (sockfd <= 0)
|
||||
{
|
||||
char port_str[16];
|
||||
struct addrinfo hints;
|
||||
@ -996,12 +1125,14 @@ BOOL freerdp_tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeou
|
||||
|
||||
status = getaddrinfo(hostname, port_str, &hints, &result);
|
||||
|
||||
if (status) {
|
||||
if (status)
|
||||
{
|
||||
WLog_ERR(TAG, "getaddrinfo: %s", gai_strerror(status));
|
||||
return FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
addr = result;
|
||||
|
||||
if ((addr->ai_family == AF_INET6) && (addr->ai_next != 0))
|
||||
{
|
||||
while ((addr = addr->ai_next))
|
||||
@ -1009,311 +1140,65 @@ BOOL freerdp_tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeou
|
||||
if (addr->ai_family == AF_INET)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!addr)
|
||||
addr = result;
|
||||
}
|
||||
|
||||
tcp->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
|
||||
if (tcp->sockfd < 0) {
|
||||
if (sockfd < 0)
|
||||
{
|
||||
freeaddrinfo(result);
|
||||
return FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!freerdp_tcp_connect_timeout(tcp->sockfd, addr->ai_addr, addr->ai_addrlen, timeout))
|
||||
if (!freerdp_tcp_connect_timeout(sockfd, addr->ai_addr, addr->ai_addrlen, timeout))
|
||||
{
|
||||
fprintf(stderr, "failed to connect to %s\n", hostname);
|
||||
freeaddrinfo(result);
|
||||
return FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
freeaddrinfo(result);
|
||||
}
|
||||
|
||||
tcp->socketBio = BIO_new_socket(tcp->sockfd, BIO_NOCLOSE);
|
||||
#endif /* NO_IPV6 */
|
||||
|
||||
(void) BIO_set_close(tcp->socketBio, BIO_NOCLOSE);
|
||||
BIO_free(tcp->socketBio);
|
||||
|
||||
tcp->socketBio = BIO_new(BIO_s_simple_socket());
|
||||
|
||||
if (!tcp->socketBio)
|
||||
return FALSE;
|
||||
|
||||
BIO_set_fd(tcp->socketBio, tcp->sockfd, BIO_CLOSE);
|
||||
}
|
||||
|
||||
BIO_get_event(tcp->socketBio, &tcp->event);
|
||||
settings->IPv6Enabled = FALSE;
|
||||
|
||||
freerdp_tcp_get_ip_address(tcp);
|
||||
free(settings->ClientAddress);
|
||||
settings->ClientAddress = freerdp_tcp_get_ip_address(sockfd);
|
||||
|
||||
option_value = 1;
|
||||
option_len = sizeof(option_value);
|
||||
optval = 1;
|
||||
optlen = sizeof(optval);
|
||||
|
||||
if (!tcp->ipcSocket)
|
||||
if (!ipcSocket)
|
||||
{
|
||||
if (setsockopt(tcp->sockfd, IPPROTO_TCP, TCP_NODELAY, (void*) &option_value, option_len) < 0)
|
||||
WLog_ERR(TAG, "unable to set TCP_NODELAY");
|
||||
if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (void*) &optval, optlen) < 0)
|
||||
WLog_ERR(TAG, "unable to set TCP_NODELAY");
|
||||
}
|
||||
|
||||
/* receive buffer must be a least 32 K */
|
||||
if (getsockopt(tcp->sockfd, SOL_SOCKET, SO_RCVBUF, (void*) &option_value, &option_len) == 0)
|
||||
if (getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (void*) &optval, &optlen) == 0)
|
||||
{
|
||||
if (option_value < (1024 * 32))
|
||||
if (optval < (1024 * 32))
|
||||
{
|
||||
option_value = 1024 * 32;
|
||||
option_len = sizeof(option_value);
|
||||
optval = 1024 * 32;
|
||||
optlen = sizeof(optval);
|
||||
|
||||
if (setsockopt(tcp->sockfd, SOL_SOCKET, SO_RCVBUF, (void*) &option_value, option_len) < 0)
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (void*) &optval, optlen) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to set receive buffer len");
|
||||
return FALSE;
|
||||
WLog_ERR(TAG, "unable to set receive buffer len");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!tcp->ipcSocket)
|
||||
if (!ipcSocket)
|
||||
{
|
||||
if (!freerdp_tcp_set_keep_alive_mode(tcp))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tcp->bufferedBio = BIO_new(BIO_s_buffered_socket());
|
||||
|
||||
if (!tcp->bufferedBio)
|
||||
return FALSE;
|
||||
|
||||
tcp->bufferedBio->ptr = tcp;
|
||||
|
||||
tcp->bufferedBio = BIO_push(tcp->bufferedBio, tcp->socketBio);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL freerdp_tcp_set_blocking_mode(rdpTcp* tcp, BOOL blocking)
|
||||
{
|
||||
return BIO_set_nonblock(tcp->socketBio, blocking ? 0 : 1) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
BOOL freerdp_tcp_set_keep_alive_mode(rdpTcp* tcp)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
UINT32 option_value;
|
||||
socklen_t option_len;
|
||||
|
||||
option_value = 1;
|
||||
option_len = sizeof(option_value);
|
||||
|
||||
if (setsockopt(tcp->sockfd, SOL_SOCKET, SO_KEEPALIVE, (void*) &option_value, option_len) < 0)
|
||||
{
|
||||
WLog_WARN(TAG, "setsockopt() SOL_SOCKET, SO_KEEPALIVE");
|
||||
}
|
||||
|
||||
#ifdef TCP_KEEPIDLE
|
||||
option_value = 5;
|
||||
option_len = sizeof(option_value);
|
||||
|
||||
if (setsockopt(tcp->sockfd, IPPROTO_TCP, TCP_KEEPIDLE, (void*) &option_value, option_len) < 0)
|
||||
{
|
||||
WLog_WARN(TAG, "setsockopt() IPPROTO_TCP, TCP_KEEPIDLE");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TCP_KEEPCNT
|
||||
option_value = 3;
|
||||
option_len = sizeof(option_value);
|
||||
|
||||
if (setsockopt(tcp->sockfd, SOL_TCP, TCP_KEEPCNT, (void*) &option_value, option_len) < 0)
|
||||
{
|
||||
WLog_WARN(TAG, "setsockopt() SOL_TCP, TCP_KEEPCNT");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TCP_KEEPINTVL
|
||||
option_value = 2;
|
||||
option_len = sizeof(option_value);
|
||||
|
||||
if (setsockopt(tcp->sockfd, SOL_TCP, TCP_KEEPINTVL, (void*) &option_value, option_len) < 0)
|
||||
{
|
||||
WLog_WARN(TAG, "setsockopt() SOL_TCP, TCP_KEEPINTVL");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__MACOSX__) || defined(__IOS__)
|
||||
option_value = 1;
|
||||
option_len = sizeof(option_value);
|
||||
if (setsockopt(tcp->sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void*) &option_value, option_len) < 0)
|
||||
{
|
||||
WLog_WARN(TAG, "setsockopt() SOL_SOCKET, SO_NOSIGPIPE");
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int freerdp_tcp_attach(rdpTcp* tcp, int sockfd)
|
||||
{
|
||||
tcp->sockfd = sockfd;
|
||||
|
||||
ringbuffer_commit_read_bytes(&tcp->xmitBuffer, ringbuffer_used(&tcp->xmitBuffer));
|
||||
|
||||
if (tcp->socketBio)
|
||||
{
|
||||
if (BIO_set_fd(tcp->socketBio, sockfd, BIO_CLOSE) < 0)
|
||||
if (!freerdp_tcp_set_keep_alive_mode(sockfd))
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
tcp->socketBio = BIO_new(BIO_s_simple_socket());
|
||||
|
||||
if (!tcp->socketBio)
|
||||
return -1;
|
||||
|
||||
BIO_set_fd(tcp->socketBio, sockfd, BIO_CLOSE);
|
||||
}
|
||||
|
||||
if (!tcp->bufferedBio)
|
||||
{
|
||||
tcp->bufferedBio = BIO_new(BIO_s_buffered_socket());
|
||||
|
||||
if (!tcp->bufferedBio)
|
||||
return FALSE;
|
||||
|
||||
tcp->bufferedBio->ptr = tcp;
|
||||
|
||||
tcp->bufferedBio = BIO_push(tcp->bufferedBio, tcp->socketBio);
|
||||
}
|
||||
|
||||
BIO_get_event(tcp->socketBio, &tcp->event);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
HANDLE freerdp_tcp_get_event_handle(rdpTcp* tcp)
|
||||
{
|
||||
if (!tcp)
|
||||
return NULL;
|
||||
|
||||
return tcp->event;
|
||||
}
|
||||
|
||||
int freerdp_tcp_wait_read(rdpTcp* tcp, DWORD dwMilliSeconds)
|
||||
{
|
||||
int status;
|
||||
|
||||
#ifdef HAVE_POLL_H
|
||||
struct pollfd pollset;
|
||||
|
||||
pollset.fd = tcp->sockfd;
|
||||
pollset.events = POLLIN;
|
||||
pollset.revents = 0;
|
||||
|
||||
do
|
||||
{
|
||||
status = poll(&pollset, 1, dwMilliSeconds);
|
||||
}
|
||||
while ((status < 0) && (errno == EINTR));
|
||||
#else
|
||||
struct timeval tv;
|
||||
fd_set rset;
|
||||
|
||||
FD_ZERO(&rset);
|
||||
FD_SET(tcp->sockfd, &rset);
|
||||
|
||||
if (dwMilliSeconds)
|
||||
{
|
||||
tv.tv_sec = dwMilliSeconds / 1000;
|
||||
tv.tv_usec = (dwMilliSeconds % 1000) * 1000;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
status = select(tcp->sockfd + 1, &rset, NULL, NULL, dwMilliSeconds ? &tv : NULL);
|
||||
}
|
||||
while ((status < 0) && (errno == EINTR));
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
int freerdp_tcp_wait_write(rdpTcp* tcp, DWORD dwMilliSeconds)
|
||||
{
|
||||
int status;
|
||||
|
||||
#ifdef HAVE_POLL_H
|
||||
struct pollfd pollset;
|
||||
|
||||
pollset.fd = tcp->sockfd;
|
||||
pollset.events = POLLOUT;
|
||||
pollset.revents = 0;
|
||||
|
||||
do
|
||||
{
|
||||
status = poll(&pollset, 1, dwMilliSeconds);
|
||||
}
|
||||
while ((status < 0) && (errno == EINTR));
|
||||
#else
|
||||
struct timeval tv;
|
||||
fd_set rset;
|
||||
|
||||
FD_ZERO(&rset);
|
||||
FD_SET(tcp->sockfd, &rset);
|
||||
|
||||
if (dwMilliSeconds)
|
||||
{
|
||||
tv.tv_sec = dwMilliSeconds / 1000;
|
||||
tv.tv_usec = (dwMilliSeconds % 1000) * 1000;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
status = select(tcp->sockfd + 1, NULL, &rset, NULL, dwMilliSeconds ? &tv : NULL);
|
||||
}
|
||||
while ((status < 0) && (errno == EINTR));
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
rdpTcp* freerdp_tcp_new(rdpSettings* settings)
|
||||
{
|
||||
rdpTcp* tcp;
|
||||
|
||||
tcp = (rdpTcp*) calloc(1, sizeof(rdpTcp));
|
||||
|
||||
if (!tcp)
|
||||
return NULL;
|
||||
|
||||
if (!ringbuffer_init(&tcp->xmitBuffer, 0x10000))
|
||||
goto out_free;
|
||||
|
||||
tcp->sockfd = -1;
|
||||
tcp->settings = settings;
|
||||
|
||||
return tcp;
|
||||
|
||||
out_free:
|
||||
free(tcp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void freerdp_tcp_free(rdpTcp* tcp)
|
||||
{
|
||||
if (!tcp)
|
||||
return;
|
||||
|
||||
ringbuffer_destroy(&tcp->xmitBuffer);
|
||||
|
||||
if (tcp->socketBio)
|
||||
{
|
||||
BIO_free(tcp->socketBio);
|
||||
tcp->socketBio = NULL;
|
||||
}
|
||||
|
||||
if (tcp->bufferedBio)
|
||||
{
|
||||
BIO_free(tcp->bufferedBio);
|
||||
tcp->bufferedBio = NULL;
|
||||
}
|
||||
|
||||
free(tcp);
|
||||
return sockfd;
|
||||
}
|
||||
|
@ -31,12 +31,9 @@
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/winsock.h>
|
||||
|
||||
#include <freerdp/utils/ringbuffer.h>
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#ifndef MSG_NOSIGNAL
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
#include <freerdp/utils/ringbuffer.h>
|
||||
|
||||
#define BIO_TYPE_TSG 65
|
||||
#define BIO_TYPE_SIMPLE 66
|
||||
@ -46,40 +43,23 @@
|
||||
#define BIO_C_GET_SOCKET 1102
|
||||
#define BIO_C_GET_EVENT 1103
|
||||
#define BIO_C_SET_NONBLOCK 1104
|
||||
#define BIO_C_READ_BLOCKED 1105
|
||||
#define BIO_C_WRITE_BLOCKED 1106
|
||||
#define BIO_C_WAIT_READ 1107
|
||||
#define BIO_C_WAIT_WRITE 1108
|
||||
|
||||
#define BIO_set_socket(b, s, c) BIO_ctrl(b, BIO_C_SET_SOCKET, c, s);
|
||||
#define BIO_get_socket(b, c) BIO_ctrl(b, BIO_C_GET_SOCKET, 0, (char*) c)
|
||||
#define BIO_get_event(b, c) BIO_ctrl(b, BIO_C_GET_EVENT, 0, (char*) c)
|
||||
#define BIO_set_nonblock(b, c) BIO_ctrl(b, BIO_C_SET_NONBLOCK, c, NULL)
|
||||
#define BIO_read_blocked(b) BIO_ctrl(b, BIO_C_READ_BLOCKED, 0, NULL)
|
||||
#define BIO_write_blocked(b) BIO_ctrl(b, BIO_C_WRITE_BLOCKED, 0, NULL)
|
||||
#define BIO_wait_read(b, c) BIO_ctrl(b, BIO_C_WAIT_READ, c, NULL)
|
||||
#define BIO_wait_write(b, c) BIO_ctrl(b, BIO_C_WAIT_WRITE, c, NULL)
|
||||
|
||||
typedef struct rdp_tcp rdpTcp;
|
||||
BIO_METHOD* BIO_s_simple_socket(void);
|
||||
BIO_METHOD* BIO_s_buffered_socket(void);
|
||||
|
||||
struct rdp_tcp
|
||||
{
|
||||
int sockfd;
|
||||
BOOL ipcSocket;
|
||||
char ip_address[32];
|
||||
BYTE mac_address[6];
|
||||
rdpSettings* settings;
|
||||
BIO* socketBio;
|
||||
BIO* bufferedBio;
|
||||
RingBuffer xmitBuffer;
|
||||
BOOL writeBlocked;
|
||||
BOOL readBlocked;
|
||||
HANDLE event;
|
||||
};
|
||||
|
||||
BOOL freerdp_tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout);
|
||||
int freerdp_tcp_read(rdpTcp* tcp, BYTE* data, int length);
|
||||
int freerdp_tcp_write(rdpTcp* tcp, BYTE* data, int length);
|
||||
int freerdp_tcp_wait_read(rdpTcp* tcp, DWORD dwMilliSeconds);
|
||||
int freerdp_tcp_wait_write(rdpTcp* tcp, DWORD dwMilliSeconds);
|
||||
BOOL freerdp_tcp_set_blocking_mode(rdpTcp* tcp, BOOL blocking);
|
||||
BOOL freerdp_tcp_set_keep_alive_mode(rdpTcp* tcp);
|
||||
int freerdp_tcp_attach(rdpTcp* tcp, int sockfd);
|
||||
HANDLE freerdp_tcp_get_event_handle(rdpTcp* tcp);
|
||||
|
||||
rdpTcp* freerdp_tcp_new(rdpSettings* settings);
|
||||
void freerdp_tcp_free(rdpTcp* tcp);
|
||||
int freerdp_tcp_connect(rdpSettings* settings, const char* hostname, int port, int timeout);
|
||||
|
||||
#endif /* __TCP_H */
|
||||
|
@ -67,67 +67,28 @@ wStream* transport_send_stream_init(rdpTransport* transport, int size)
|
||||
return s;
|
||||
}
|
||||
|
||||
void transport_attach(rdpTransport* transport, int sockfd)
|
||||
BOOL transport_attach(rdpTransport* transport, int sockfd)
|
||||
{
|
||||
freerdp_tcp_attach(transport->TcpIn, sockfd);
|
||||
transport->SplitInputOutput = FALSE;
|
||||
transport->frontBio = transport->TcpIn->bufferedBio;
|
||||
}
|
||||
BIO* socketBio;
|
||||
BIO* bufferedBio;
|
||||
|
||||
void transport_stop(rdpTransport* transport)
|
||||
{
|
||||
if (transport->async)
|
||||
{
|
||||
if (transport->stopEvent)
|
||||
{
|
||||
SetEvent(transport->stopEvent);
|
||||
WaitForSingleObject(transport->thread, INFINITE);
|
||||
CloseHandle(transport->thread);
|
||||
CloseHandle(transport->stopEvent);
|
||||
transport->thread = NULL;
|
||||
transport->stopEvent = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
socketBio = BIO_new(BIO_s_simple_socket());
|
||||
|
||||
BOOL transport_disconnect(rdpTransport* transport)
|
||||
{
|
||||
BOOL status = TRUE;
|
||||
|
||||
if (!transport)
|
||||
if (!socketBio)
|
||||
return FALSE;
|
||||
|
||||
transport_stop(transport);
|
||||
BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
|
||||
|
||||
if (transport->tsg)
|
||||
{
|
||||
if (transport->TsgTls)
|
||||
{
|
||||
tls_free(transport->TsgTls);
|
||||
transport->TsgTls = NULL;
|
||||
}
|
||||
bufferedBio = BIO_new(BIO_s_buffered_socket());
|
||||
|
||||
tsg_free(transport->tsg);
|
||||
transport->tsg = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (transport->TlsIn)
|
||||
tls_free(transport->TlsIn);
|
||||
if (!bufferedBio)
|
||||
return FALSE;
|
||||
|
||||
if (transport->TcpIn)
|
||||
freerdp_tcp_free(transport->TcpIn);
|
||||
}
|
||||
bufferedBio = BIO_push(bufferedBio, socketBio);
|
||||
|
||||
transport->TlsIn = NULL;
|
||||
transport->TlsOut = NULL;
|
||||
transport->frontBio = bufferedBio;
|
||||
|
||||
transport->TcpIn = NULL;
|
||||
transport->TcpOut = NULL;
|
||||
|
||||
transport->layer = TRANSPORT_LAYER_TCP;
|
||||
|
||||
return status;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL transport_connect_rdp(rdpTransport* transport)
|
||||
@ -138,45 +99,37 @@ BOOL transport_connect_rdp(rdpTransport* transport)
|
||||
|
||||
BOOL transport_connect_tls(rdpTransport* transport)
|
||||
{
|
||||
int tls_status;
|
||||
BIO* targetBio = NULL;
|
||||
rdpTls* targetTls = NULL;
|
||||
int tlsStatus;
|
||||
rdpTls* tls = NULL;
|
||||
rdpContext* context = transport->context;
|
||||
rdpSettings* settings = transport->settings;
|
||||
|
||||
if (transport->GatewayEnabled)
|
||||
{
|
||||
transport->TsgTls = tls_new(transport->settings);
|
||||
tls = transport->tls = tls_new(settings);
|
||||
transport->layer = TRANSPORT_LAYER_TSG_TLS;
|
||||
targetTls = transport->TsgTls;
|
||||
targetBio = transport->frontBio;
|
||||
}
|
||||
else
|
||||
{
|
||||
transport->TlsIn = tls_new(settings);
|
||||
targetTls = transport->TlsIn;
|
||||
targetBio = transport->TcpIn->bufferedBio;
|
||||
tls = transport->tls = tls_new(settings);
|
||||
transport->layer = TRANSPORT_LAYER_TLS;
|
||||
}
|
||||
|
||||
transport->tls = targetTls;
|
||||
transport->tls = tls;
|
||||
|
||||
targetTls->hostname = settings->ServerHostname;
|
||||
targetTls->port = settings->ServerPort;
|
||||
tls->hostname = settings->ServerHostname;
|
||||
tls->port = settings->ServerPort;
|
||||
|
||||
if (targetTls->port == 0)
|
||||
targetTls->port = 3389;
|
||||
if (tls->port == 0)
|
||||
tls->port = 3389;
|
||||
|
||||
targetTls->isGatewayTransport = FALSE;
|
||||
tls_status = tls_connect(targetTls, targetBio);
|
||||
tls->isGatewayTransport = FALSE;
|
||||
tlsStatus = tls_connect(tls, transport->frontBio);
|
||||
|
||||
if (tls_status < 1)
|
||||
if (tlsStatus < 1)
|
||||
{
|
||||
if (tls_status < 0)
|
||||
if (tlsStatus < 0)
|
||||
{
|
||||
if (!connectErrorCode)
|
||||
connectErrorCode = TLSCONNECTERROR;
|
||||
|
||||
if (!freerdp_get_last_error(context))
|
||||
freerdp_set_last_error(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
|
||||
}
|
||||
@ -189,7 +142,7 @@ BOOL transport_connect_tls(rdpTransport* transport)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
transport->frontBio = targetTls->bio;
|
||||
transport->frontBio = tls->bio;
|
||||
|
||||
if (!transport->frontBio)
|
||||
{
|
||||
@ -202,84 +155,51 @@ BOOL transport_connect_tls(rdpTransport* transport)
|
||||
|
||||
BOOL transport_connect_nla(rdpTransport* transport)
|
||||
{
|
||||
freerdp* instance;
|
||||
rdpSettings* settings;
|
||||
rdpCredssp* credSsp;
|
||||
settings = transport->settings;
|
||||
instance = (freerdp*) settings->instance;
|
||||
rdpContext* context = transport->context;
|
||||
rdpSettings* settings = context->settings;
|
||||
freerdp* instance = context->instance;
|
||||
rdpRdp* rdp = context->rdp;
|
||||
|
||||
if (!transport_connect_tls(transport))
|
||||
return FALSE;
|
||||
|
||||
/* Network Level Authentication */
|
||||
|
||||
if (!settings->Authentication)
|
||||
return TRUE;
|
||||
|
||||
if (!transport->credssp)
|
||||
{
|
||||
transport->credssp = credssp_new(instance, transport, settings);
|
||||
rdp->nla = nla_new(instance, transport, settings);
|
||||
|
||||
if (!transport->credssp)
|
||||
if (!rdp->nla)
|
||||
return FALSE;
|
||||
|
||||
transport_set_nla_mode(transport, TRUE);
|
||||
|
||||
if (settings->AuthenticationServiceClass)
|
||||
{
|
||||
rdp->nla->ServicePrincipalName =
|
||||
nla_make_spn(settings->AuthenticationServiceClass, settings->ServerHostname);
|
||||
|
||||
if (!rdp->nla->ServicePrincipalName)
|
||||
return FALSE;
|
||||
|
||||
transport_set_nla_mode(transport, TRUE);
|
||||
|
||||
if (settings->AuthenticationServiceClass)
|
||||
{
|
||||
transport->credssp->ServicePrincipalName =
|
||||
credssp_make_spn(settings->AuthenticationServiceClass, settings->ServerHostname);
|
||||
|
||||
if (!transport->credssp->ServicePrincipalName)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
credSsp = transport->credssp;
|
||||
|
||||
if (credssp_authenticate(credSsp) < 0)
|
||||
if (nla_client_begin(rdp->nla) < 0)
|
||||
{
|
||||
if (!connectErrorCode)
|
||||
connectErrorCode = AUTHENTICATIONERROR;
|
||||
if (!freerdp_get_last_error(context))
|
||||
freerdp_set_last_error(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
|
||||
|
||||
if (!freerdp_get_last_error(instance->context))
|
||||
{
|
||||
freerdp_set_last_error(instance->context, FREERDP_ERROR_AUTHENTICATION_FAILED);
|
||||
}
|
||||
|
||||
WLog_ERR(TAG, "Authentication failure, check credentials."
|
||||
"If credentials are valid, the NTLMSSP implementation may be to blame.");
|
||||
transport_set_nla_mode(transport, FALSE);
|
||||
credssp_free(credSsp);
|
||||
transport->credssp = NULL;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
transport_set_nla_mode(transport, FALSE);
|
||||
credssp_free(credSsp);
|
||||
transport->credssp = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16 port, int timeout)
|
||||
{
|
||||
rdpTsg* tsg;
|
||||
|
||||
tsg = tsg_new(transport);
|
||||
|
||||
if (!tsg)
|
||||
return FALSE;
|
||||
|
||||
transport->tsg = tsg;
|
||||
|
||||
if (!tsg_connect(tsg, hostname, port, timeout))
|
||||
return FALSE;
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_NLA);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port, int timeout)
|
||||
{
|
||||
int sockfd;
|
||||
BOOL status = FALSE;
|
||||
rdpSettings* settings = transport->settings;
|
||||
|
||||
@ -287,18 +207,29 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por
|
||||
|
||||
if (transport->GatewayEnabled)
|
||||
{
|
||||
if (!transport_tsg_connect(transport, hostname, port, timeout))
|
||||
transport->tsg = tsg_new(transport);
|
||||
|
||||
if (!transport->tsg)
|
||||
return FALSE;
|
||||
|
||||
if (!tsg_connect(transport->tsg, hostname, port, timeout))
|
||||
return FALSE;
|
||||
|
||||
transport->frontBio = transport->tsg->bio;
|
||||
transport->layer = TRANSPORT_LAYER_TSG;
|
||||
|
||||
status = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
transport->TcpIn = freerdp_tcp_new(settings);
|
||||
sockfd = freerdp_tcp_connect(settings, hostname, port, timeout);
|
||||
|
||||
status = freerdp_tcp_connect(transport->TcpIn, hostname, port, timeout);
|
||||
transport->SplitInputOutput = FALSE;
|
||||
transport->frontBio = transport->TcpIn->bufferedBio;
|
||||
if (sockfd < 1)
|
||||
return FALSE;
|
||||
|
||||
transport_attach(transport, sockfd);
|
||||
|
||||
status = TRUE;
|
||||
}
|
||||
|
||||
if (status)
|
||||
@ -324,15 +255,16 @@ BOOL transport_accept_tls(rdpTransport* transport)
|
||||
{
|
||||
rdpSettings* settings = transport->settings;
|
||||
|
||||
if (!transport->TlsIn)
|
||||
transport->TlsIn = tls_new(transport->settings);
|
||||
if (!transport->tls)
|
||||
transport->tls = tls_new(transport->settings);
|
||||
|
||||
transport->layer = TRANSPORT_LAYER_TLS;
|
||||
|
||||
if (!tls_accept(transport->TlsIn, transport->TcpIn->bufferedBio, settings->CertificateFile, settings->PrivateKeyFile))
|
||||
if (!tls_accept(transport->tls, transport->frontBio, settings->CertificateFile, settings->PrivateKeyFile))
|
||||
return FALSE;
|
||||
|
||||
transport->frontBio = transport->TlsIn->bio;
|
||||
transport->frontBio = transport->tls->bio;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -341,77 +273,42 @@ BOOL transport_accept_nla(rdpTransport* transport)
|
||||
rdpSettings* settings = transport->settings;
|
||||
freerdp* instance = (freerdp*) settings->instance;
|
||||
|
||||
if (!transport->TlsIn)
|
||||
transport->TlsIn = tls_new(transport->settings);
|
||||
if (!transport->tls)
|
||||
transport->tls = tls_new(transport->settings);
|
||||
|
||||
transport->layer = TRANSPORT_LAYER_TLS;
|
||||
|
||||
if (!tls_accept(transport->TlsIn, transport->TcpIn->bufferedBio, settings->CertificateFile, settings->PrivateKeyFile))
|
||||
if (!tls_accept(transport->tls, transport->frontBio, settings->CertificateFile, settings->PrivateKeyFile))
|
||||
return FALSE;
|
||||
|
||||
transport->frontBio = transport->TlsIn->bio;
|
||||
transport->frontBio = transport->tls->bio;
|
||||
|
||||
/* Network Level Authentication */
|
||||
|
||||
if (!settings->Authentication)
|
||||
return TRUE;
|
||||
|
||||
if (!transport->credssp)
|
||||
if (!transport->nla)
|
||||
{
|
||||
transport->credssp = credssp_new(instance, transport, settings);
|
||||
transport->nla = nla_new(instance, transport, settings);
|
||||
transport_set_nla_mode(transport, TRUE);
|
||||
}
|
||||
|
||||
if (credssp_authenticate(transport->credssp) < 0)
|
||||
if (nla_authenticate(transport->nla) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "client authentication failure");
|
||||
transport_set_nla_mode(transport, FALSE);
|
||||
credssp_free(transport->credssp);
|
||||
transport->credssp = NULL;
|
||||
tls_set_alert_code(transport->TlsIn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
|
||||
nla_free(transport->nla);
|
||||
transport->nla = NULL;
|
||||
tls_set_alert_code(transport->tls, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* don't free credssp module yet, we need to copy the credentials from it first */
|
||||
/* don't free nla module yet, we need to copy the credentials from it first */
|
||||
transport_set_nla_mode(transport, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int transport_wait_for_read(rdpTransport* transport)
|
||||
{
|
||||
rdpTcp* tcpIn = transport->TcpIn;
|
||||
|
||||
if (tcpIn->readBlocked)
|
||||
{
|
||||
return freerdp_tcp_wait_read(tcpIn, 10);
|
||||
}
|
||||
else if (tcpIn->writeBlocked)
|
||||
{
|
||||
return freerdp_tcp_wait_write(tcpIn, 10);
|
||||
}
|
||||
|
||||
USleep(1000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int transport_wait_for_write(rdpTransport* transport)
|
||||
{
|
||||
rdpTcp* tcpOut;
|
||||
tcpOut = transport->SplitInputOutput ? transport->TcpOut : transport->TcpIn;
|
||||
|
||||
if (tcpOut->writeBlocked)
|
||||
{
|
||||
return freerdp_tcp_wait_write(tcpOut, 10);
|
||||
}
|
||||
else if (tcpOut->readBlocked)
|
||||
{
|
||||
return freerdp_tcp_wait_read(tcpOut, 10);
|
||||
}
|
||||
|
||||
USleep(1000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int transport_read_layer(rdpTransport* transport, BYTE* data, int bytes)
|
||||
{
|
||||
int read = 0;
|
||||
@ -440,9 +337,8 @@ int transport_read_layer(rdpTransport* transport, BYTE* data, int bytes)
|
||||
if (!transport->blocking)
|
||||
return read;
|
||||
|
||||
/* blocking means that we can't continue until we have read the number of
|
||||
* requested bytes */
|
||||
if (transport_wait_for_read(transport) < 0)
|
||||
/* blocking means that we can't continue until we have read the number of requested bytes */
|
||||
if (BIO_wait_read(transport->frontBio, 100) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "error when selecting for read");
|
||||
return -1;
|
||||
@ -505,6 +401,7 @@ int transport_read_pdu(rdpTransport* transport, wStream* s)
|
||||
int position;
|
||||
int pduLength;
|
||||
BYTE* header;
|
||||
|
||||
position = 0;
|
||||
pduLength = 0;
|
||||
|
||||
@ -518,7 +415,7 @@ int transport_read_pdu(rdpTransport* transport, wStream* s)
|
||||
/* Make sure there is enough space for the longest header within the stream */
|
||||
Stream_EnsureCapacity(s, 4);
|
||||
|
||||
/* Make sure at least two bytes are read for futher processing */
|
||||
/* Make sure at least two bytes are read for further processing */
|
||||
if (position < 2 && (status = transport_read_layer_bytes(transport, s, 2 - position)) != 1)
|
||||
{
|
||||
/* No data available at the moment */
|
||||
@ -618,17 +515,6 @@ int transport_read_pdu(rdpTransport* transport, wStream* s)
|
||||
if (status != 1)
|
||||
return status;
|
||||
|
||||
#ifdef WITH_DEBUG_TRANSPORT
|
||||
|
||||
/* dump when whole PDU is read */
|
||||
if (Stream_GetPosition(s) >= pduLength)
|
||||
{
|
||||
WLog_DBG(TAG, "Local < Remote");
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), pduLength);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (Stream_GetPosition(s) >= pduLength)
|
||||
WLog_Packet(WLog_Get(TAG), WLOG_TRACE, Stream_Buffer(s), pduLength, WLOG_PACKET_INBOUND);
|
||||
|
||||
@ -637,24 +523,15 @@ int transport_read_pdu(rdpTransport* transport, wStream* s)
|
||||
return Stream_Length(s);
|
||||
}
|
||||
|
||||
BOOL transport_bio_buffered_drain(BIO* bio);
|
||||
|
||||
int transport_write(rdpTransport* transport, wStream* s)
|
||||
{
|
||||
int length;
|
||||
int status = -1;
|
||||
|
||||
EnterCriticalSection(&(transport->WriteLock));
|
||||
|
||||
length = Stream_GetPosition(s);
|
||||
Stream_SetPosition(s, 0);
|
||||
#ifdef WITH_DEBUG_TRANSPORT
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
WLog_DBG(TAG, "Local > Remote");
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), length);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
@ -678,7 +555,7 @@ int transport_write(rdpTransport* transport, wStream* s)
|
||||
if (!transport->blocking)
|
||||
return status;
|
||||
|
||||
if (transport_wait_for_write(transport) < 0)
|
||||
if (BIO_wait_write(transport->frontBio, 100) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "error when selecting for write");
|
||||
return -1;
|
||||
@ -689,20 +566,17 @@ int transport_write(rdpTransport* transport, wStream* s)
|
||||
|
||||
if (transport->blocking || transport->settings->WaitForOutputBufferFlush)
|
||||
{
|
||||
/* blocking transport, we must ensure the write buffer is really empty */
|
||||
rdpTcp* out = transport->SplitInputOutput ? transport->TcpOut : transport->TcpIn;
|
||||
|
||||
while (out->writeBlocked)
|
||||
while (BIO_write_blocked(transport->frontBio))
|
||||
{
|
||||
if (transport_wait_for_write(transport) < 0)
|
||||
if (BIO_wait_write(transport->frontBio, 100) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "error when selecting for write");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!transport_bio_buffered_drain(out->bufferedBio))
|
||||
if (BIO_flush(transport->frontBio) < 1)
|
||||
{
|
||||
WLog_ERR(TAG, "error when draining outputBuffer");
|
||||
WLog_ERR(TAG, "error when flushing outputBuffer");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -725,92 +599,54 @@ int transport_write(rdpTransport* transport, wStream* s)
|
||||
return status;
|
||||
}
|
||||
|
||||
void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount)
|
||||
UINT32 transport_get_event_handles(rdpTransport* transport, HANDLE* events)
|
||||
{
|
||||
void* pfd;
|
||||
UINT32 nCount = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
rfds[*rcount] = transport->TcpIn->event;
|
||||
(*rcount)++;
|
||||
#else
|
||||
rfds[*rcount] = (void*)(long)(transport->TcpIn->sockfd);
|
||||
(*rcount)++;
|
||||
#endif
|
||||
|
||||
pfd = GetEventWaitObject(transport->ReceiveEvent);
|
||||
|
||||
if (pfd)
|
||||
{
|
||||
rfds[*rcount] = pfd;
|
||||
(*rcount)++;
|
||||
}
|
||||
|
||||
if (transport->GatewayEvent)
|
||||
{
|
||||
pfd = GetEventWaitObject(transport->GatewayEvent);
|
||||
|
||||
if (pfd)
|
||||
{
|
||||
rfds[*rcount] = pfd;
|
||||
(*rcount)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DWORD transport_get_event_handles(rdpTransport* transport, HANDLE* events)
|
||||
{
|
||||
DWORD nCount = 0;
|
||||
|
||||
if (events)
|
||||
events[nCount] = freerdp_tcp_get_event_handle(transport->TcpIn);
|
||||
nCount++;
|
||||
|
||||
if (transport->ReceiveEvent)
|
||||
if (!transport->GatewayEnabled)
|
||||
{
|
||||
if (events)
|
||||
events[nCount] = transport->ReceiveEvent;
|
||||
BIO_get_event(transport->frontBio, &events[nCount]);
|
||||
nCount++;
|
||||
}
|
||||
|
||||
if (transport->GatewayEvent)
|
||||
else
|
||||
{
|
||||
if (events)
|
||||
events[nCount] = transport->GatewayEvent;
|
||||
nCount++;
|
||||
nCount += tsg_get_event_handles(transport->tsg, events);
|
||||
}
|
||||
|
||||
return nCount;
|
||||
}
|
||||
|
||||
BOOL tranport_is_write_blocked(rdpTransport* transport)
|
||||
void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount)
|
||||
{
|
||||
if (transport->TcpIn->writeBlocked)
|
||||
return TRUE;
|
||||
UINT32 index;
|
||||
UINT32 nCount;
|
||||
HANDLE events[64];
|
||||
|
||||
return transport->SplitInputOutput &&
|
||||
transport->TcpOut &&
|
||||
transport->TcpOut->writeBlocked;
|
||||
nCount = transport_get_event_handles(transport, events);
|
||||
|
||||
for (index = 0; index < nCount; index++)
|
||||
{
|
||||
rfds[*rcount] = GetEventWaitObject(events[index]);
|
||||
(*rcount)++;
|
||||
}
|
||||
}
|
||||
|
||||
int tranport_drain_output_buffer(rdpTransport* transport)
|
||||
BOOL transport_is_write_blocked(rdpTransport* transport)
|
||||
{
|
||||
return BIO_write_blocked(transport->frontBio);
|
||||
}
|
||||
|
||||
int transport_drain_output_buffer(rdpTransport* transport)
|
||||
{
|
||||
BOOL status = FALSE;
|
||||
|
||||
/* First try to send some accumulated bytes in the send buffer */
|
||||
if (transport->TcpIn->writeBlocked)
|
||||
if (BIO_write_blocked(transport->frontBio))
|
||||
{
|
||||
if (!transport_bio_buffered_drain(transport->TcpIn->bufferedBio))
|
||||
if (BIO_flush(transport->frontBio) < 1)
|
||||
return -1;
|
||||
|
||||
status |= transport->TcpIn->writeBlocked;
|
||||
}
|
||||
|
||||
if (transport->SplitInputOutput && transport->TcpOut && transport->TcpOut->writeBlocked)
|
||||
{
|
||||
if (!transport_bio_buffered_drain(transport->TcpOut->bufferedBio))
|
||||
return -1;
|
||||
|
||||
status |= transport->TcpOut->writeBlocked;
|
||||
status |= BIO_write_blocked(transport->frontBio);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -825,8 +661,6 @@ int transport_check_fds(rdpTransport* transport)
|
||||
if (!transport)
|
||||
return -1;
|
||||
|
||||
ResetEvent(transport->ReceiveEvent);
|
||||
|
||||
/**
|
||||
* Loop through and read all available PDUs. Since multiple
|
||||
* PDUs can exist, it's important to deliver them all before
|
||||
@ -876,16 +710,12 @@ int transport_check_fds(rdpTransport* transport)
|
||||
|
||||
BOOL transport_set_blocking_mode(rdpTransport* transport, BOOL blocking)
|
||||
{
|
||||
BOOL status = TRUE;
|
||||
|
||||
transport->blocking = blocking;
|
||||
|
||||
if (!transport->SplitInputOutput)
|
||||
{
|
||||
status &= freerdp_tcp_set_blocking_mode(transport->TcpIn, blocking);
|
||||
}
|
||||
if (!BIO_set_nonblock(transport->frontBio, blocking ? FALSE : TRUE))
|
||||
return FALSE;
|
||||
|
||||
return status;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void transport_set_gateway_enabled(rdpTransport* transport, BOOL GatewayEnabled)
|
||||
@ -898,6 +728,58 @@ void transport_set_nla_mode(rdpTransport* transport, BOOL NlaMode)
|
||||
transport->NlaMode = NlaMode;
|
||||
}
|
||||
|
||||
void transport_stop(rdpTransport* transport)
|
||||
{
|
||||
if (transport->async)
|
||||
{
|
||||
if (transport->stopEvent)
|
||||
{
|
||||
SetEvent(transport->stopEvent);
|
||||
WaitForSingleObject(transport->thread, INFINITE);
|
||||
CloseHandle(transport->thread);
|
||||
CloseHandle(transport->stopEvent);
|
||||
transport->thread = NULL;
|
||||
transport->stopEvent = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL transport_disconnect(rdpTransport* transport)
|
||||
{
|
||||
BOOL status = TRUE;
|
||||
|
||||
if (!transport)
|
||||
return FALSE;
|
||||
|
||||
transport_stop(transport);
|
||||
|
||||
if (transport->tsg)
|
||||
{
|
||||
if (transport->tls)
|
||||
{
|
||||
tls_free(transport->tls);
|
||||
transport->tls = NULL;
|
||||
}
|
||||
|
||||
tsg_free(transport->tsg);
|
||||
transport->tsg = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (transport->tls)
|
||||
{
|
||||
tls_free(transport->tls);
|
||||
transport->tls = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
transport->frontBio = NULL;
|
||||
|
||||
transport->layer = TRANSPORT_LAYER_TCP;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void* transport_client_thread(void* arg)
|
||||
{
|
||||
DWORD status;
|
||||
@ -968,12 +850,10 @@ rdpTransport* transport_new(rdpContext* context)
|
||||
transport->context = context;
|
||||
transport->settings = context->settings;
|
||||
|
||||
/* a small 0.1ms delay when transport is blocking. */
|
||||
transport->SleepInterval = 100;
|
||||
transport->ReceivePool = StreamPool_New(TRUE, BUFFER_SIZE);
|
||||
|
||||
if (!transport->ReceivePool)
|
||||
goto out_free_tcpin;
|
||||
goto out_free_transport;
|
||||
|
||||
/* receive buffer for non-blocking read. */
|
||||
transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0);
|
||||
@ -981,15 +861,10 @@ rdpTransport* transport_new(rdpContext* context)
|
||||
if (!transport->ReceiveBuffer)
|
||||
goto out_free_receivepool;
|
||||
|
||||
transport->ReceiveEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
if (!transport->ReceiveEvent || transport->ReceiveEvent == INVALID_HANDLE_VALUE)
|
||||
goto out_free_receivebuffer;
|
||||
|
||||
transport->connectedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
if (!transport->connectedEvent || transport->connectedEvent == INVALID_HANDLE_VALUE)
|
||||
goto out_free_receiveEvent;
|
||||
goto out_free_receivebuffer;
|
||||
|
||||
transport->blocking = TRUE;
|
||||
transport->GatewayEnabled = FALSE;
|
||||
@ -1006,14 +881,11 @@ out_free_readlock:
|
||||
DeleteCriticalSection(&(transport->ReadLock));
|
||||
out_free_connectedEvent:
|
||||
CloseHandle(transport->connectedEvent);
|
||||
out_free_receiveEvent:
|
||||
CloseHandle(transport->ReceiveEvent);
|
||||
out_free_receivebuffer:
|
||||
StreamPool_Return(transport->ReceivePool, transport->ReceiveBuffer);
|
||||
out_free_receivepool:
|
||||
StreamPool_Free(transport->ReceivePool);
|
||||
out_free_tcpin:
|
||||
freerdp_tcp_free(transport->TcpIn);
|
||||
out_free_transport:
|
||||
free(transport);
|
||||
return NULL;
|
||||
}
|
||||
@ -1029,7 +901,6 @@ void transport_free(rdpTransport* transport)
|
||||
Stream_Release(transport->ReceiveBuffer);
|
||||
|
||||
StreamPool_Free(transport->ReceivePool);
|
||||
CloseHandle(transport->ReceiveEvent);
|
||||
CloseHandle(transport->connectedEvent);
|
||||
DeleteCriticalSection(&(transport->ReadLock));
|
||||
DeleteCriticalSection(&(transport->WriteLock));
|
||||
|
@ -58,28 +58,19 @@ struct rdp_transport
|
||||
BIO* frontBio;
|
||||
rdpTsg* tsg;
|
||||
rdpTls* tls;
|
||||
rdpTcp* TcpIn;
|
||||
rdpTcp* TcpOut;
|
||||
rdpTls* TlsIn;
|
||||
rdpTls* TlsOut;
|
||||
rdpTls* TsgTls;
|
||||
rdpContext* context;
|
||||
rdpCredssp* credssp;
|
||||
rdpNla* nla;
|
||||
rdpSettings* settings;
|
||||
UINT32 SleepInterval;
|
||||
void* ReceiveExtra;
|
||||
wStream* ReceiveBuffer;
|
||||
TransportRecv ReceiveCallback;
|
||||
HANDLE ReceiveEvent;
|
||||
HANDLE GatewayEvent;
|
||||
BOOL blocking;
|
||||
BOOL SplitInputOutput;
|
||||
wStreamPool* ReceivePool;
|
||||
HANDLE connectedEvent;
|
||||
HANDLE stopEvent;
|
||||
HANDLE thread;
|
||||
BOOL async;
|
||||
BOOL NlaMode;
|
||||
BOOL blocking;
|
||||
BOOL GatewayEnabled;
|
||||
CRITICAL_SECTION ReadLock;
|
||||
CRITICAL_SECTION WriteLock;
|
||||
@ -87,7 +78,7 @@ struct rdp_transport
|
||||
|
||||
wStream* transport_send_stream_init(rdpTransport* transport, int size);
|
||||
BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port, int timeout);
|
||||
void transport_attach(rdpTransport* transport, int sockfd);
|
||||
BOOL transport_attach(rdpTransport* transport, int sockfd);
|
||||
BOOL transport_disconnect(rdpTransport* transport);
|
||||
BOOL transport_connect_rdp(rdpTransport* transport);
|
||||
BOOL transport_connect_tls(rdpTransport* transport);
|
||||
@ -102,13 +93,13 @@ int transport_write(rdpTransport* transport, wStream* s);
|
||||
void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount);
|
||||
int transport_check_fds(rdpTransport* transport);
|
||||
|
||||
DWORD transport_get_event_handles(rdpTransport* transport, HANDLE* events);
|
||||
UINT32 transport_get_event_handles(rdpTransport* transport, HANDLE* events);
|
||||
|
||||
BOOL transport_set_blocking_mode(rdpTransport* transport, BOOL blocking);
|
||||
void transport_set_gateway_enabled(rdpTransport* transport, BOOL GatewayEnabled);
|
||||
void transport_set_nla_mode(rdpTransport* transport, BOOL NlaMode);
|
||||
BOOL tranport_is_write_blocked(rdpTransport* transport);
|
||||
int tranport_drain_output_buffer(rdpTransport* transport);
|
||||
BOOL transport_is_write_blocked(rdpTransport* transport);
|
||||
int transport_drain_output_buffer(rdpTransport* transport);
|
||||
|
||||
wStream* transport_receive_pool_take(rdpTransport* transport);
|
||||
int transport_receive_pool_return(rdpTransport* transport, wStream* pdu);
|
||||
|
@ -879,162 +879,34 @@ BIO *findBufferedBio(BIO *front)
|
||||
|
||||
int tls_write_all(rdpTls* tls, const BYTE* data, int length)
|
||||
{
|
||||
int i;
|
||||
int status;
|
||||
int nchunks;
|
||||
int committedBytes;
|
||||
rdpTcp *tcp;
|
||||
#ifdef HAVE_POLL_H
|
||||
struct pollfd pollfds;
|
||||
#else
|
||||
fd_set rset, wset;
|
||||
fd_set *rsetPtr, *wsetPtr;
|
||||
struct timeval tv;
|
||||
#endif
|
||||
int offset = 0;
|
||||
BIO* bio = tls->bio;
|
||||
DataChunk chunks[2];
|
||||
|
||||
BIO* bufferedBio = findBufferedBio(bio);
|
||||
|
||||
if (!bufferedBio)
|
||||
while (offset < length)
|
||||
{
|
||||
WLog_ERR(TAG, "error unable to retrieve the bufferedBio in the BIO chain");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcp = (rdpTcp*) bufferedBio->ptr;
|
||||
|
||||
do
|
||||
{
|
||||
status = BIO_write(bio, data, length);
|
||||
status = BIO_write(bio, &data[offset], length - offset);
|
||||
|
||||
if (status > 0)
|
||||
break;
|
||||
|
||||
if (!BIO_should_retry(bio))
|
||||
return -1;
|
||||
|
||||
#ifdef HAVE_POLL_H
|
||||
pollfds.fd = tcp->sockfd;
|
||||
pollfds.revents = 0;
|
||||
pollfds.events = 0;
|
||||
|
||||
if (tcp->writeBlocked)
|
||||
{
|
||||
pollfds.events |= POLLOUT;
|
||||
}
|
||||
else if (tcp->readBlocked)
|
||||
{
|
||||
pollfds.events |= POLLIN;
|
||||
offset += status;
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_ERR(TAG, "weird we're blocked but the underlying is not read or write blocked !");
|
||||
USleep(10);
|
||||
continue;
|
||||
}
|
||||
if (!BIO_should_retry(bio))
|
||||
return -1;
|
||||
|
||||
do
|
||||
{
|
||||
status = poll(&pollfds, 1, 100);
|
||||
}
|
||||
while ((status < 0) && (errno == EINTR));
|
||||
#else
|
||||
/* we try to handle SSL want_read and want_write nicely */
|
||||
rsetPtr = wsetPtr = NULL;
|
||||
if (BIO_write_blocked(bio))
|
||||
status = BIO_wait_write(bio, 100);
|
||||
else if (BIO_read_blocked(bio))
|
||||
status = BIO_wait_read(bio, 100);
|
||||
else
|
||||
USleep(100);
|
||||
|
||||
if (tcp->writeBlocked)
|
||||
{
|
||||
wsetPtr = &wset;
|
||||
FD_ZERO(&wset);
|
||||
FD_SET(tcp->sockfd, &wset);
|
||||
if (status < 0)
|
||||
return -1;
|
||||
}
|
||||
else if (tcp->readBlocked)
|
||||
{
|
||||
rsetPtr = &rset;
|
||||
FD_ZERO(&rset);
|
||||
FD_SET(tcp->sockfd, &rset);
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_ERR(TAG, "weird we're blocked but the underlying is not read or write blocked !");
|
||||
USleep(10);
|
||||
continue;
|
||||
}
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 100 * 1000;
|
||||
|
||||
status = _select(tcp->sockfd + 1, rsetPtr, wsetPtr, NULL, &tv);
|
||||
#endif
|
||||
if (status < 0)
|
||||
return -1;
|
||||
}
|
||||
while (TRUE);
|
||||
|
||||
/* make sure the output buffer is empty */
|
||||
|
||||
do
|
||||
{
|
||||
committedBytes = 0;
|
||||
|
||||
if (ringbuffer_used(&tcp->xmitBuffer) < 1)
|
||||
break;
|
||||
|
||||
nchunks = ringbuffer_peek(&tcp->xmitBuffer, chunks, ringbuffer_used(&tcp->xmitBuffer));
|
||||
|
||||
if (nchunks < 1)
|
||||
break;
|
||||
|
||||
for (i = 0; i < nchunks; i++)
|
||||
{
|
||||
while (chunks[i].size)
|
||||
{
|
||||
status = BIO_write(tcp->socketBio, chunks[i].data, chunks[i].size);
|
||||
|
||||
if (status > 0)
|
||||
{
|
||||
chunks[i].size -= status;
|
||||
chunks[i].data += status;
|
||||
committedBytes += status;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!BIO_should_retry(tcp->socketBio))
|
||||
goto out_fail;
|
||||
|
||||
#ifdef HAVE_POLL_H
|
||||
pollfds.fd = tcp->sockfd;
|
||||
pollfds.events = POLLIN;
|
||||
pollfds.revents = 0;
|
||||
|
||||
do
|
||||
{
|
||||
status = poll(&pollfds, 1, 100);
|
||||
}
|
||||
while ((status < 0) && (errno == EINTR));
|
||||
#else
|
||||
FD_ZERO(&rset);
|
||||
FD_SET(tcp->sockfd, &rset);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 100 * 1000;
|
||||
|
||||
status = _select(tcp->sockfd + 1, &rset, NULL, NULL, &tv);
|
||||
#endif
|
||||
if (status < 0)
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ringbuffer_commit_read_bytes(&tcp->xmitBuffer, committedBytes);
|
||||
continue;
|
||||
|
||||
out_fail:
|
||||
ringbuffer_commit_read_bytes(&tcp->xmitBuffer, committedBytes);
|
||||
return -1;
|
||||
}
|
||||
while (TRUE);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
@ -56,6 +56,12 @@
|
||||
#define _getprotobynumber getprotobynumber
|
||||
#define _getprotobyname getprotobyname
|
||||
|
||||
#define _IFF_UP IFF_UP
|
||||
#define _IFF_BROADCAST IFF_BROADCAST
|
||||
#define _IFF_LOOPBACK IFF_LOOPBACK
|
||||
#define _IFF_POINTTOPOINT IFF_POINTTOPOINT
|
||||
#define _IFF_MULTICAST IFF_MULTICAST
|
||||
|
||||
#if (_WIN32_WINNT < 0x0600)
|
||||
|
||||
PCSTR inet_ntop(INT Family, PVOID pAddr, PSTR pStringBuf, size_t StringBufSize);
|
||||
@ -155,6 +161,123 @@ typedef struct WSAData
|
||||
#define MAKEWORD(a,b) ((WORD)(((BYTE)((DWORD_PTR)(a) & 0xFF)) | (((WORD)((BYTE)((DWORD_PTR)(b) & 0xFF))) << 8)))
|
||||
#endif
|
||||
|
||||
typedef struct in6_addr IN6_ADDR;
|
||||
typedef struct in6_addr* PIN6_ADDR;
|
||||
typedef struct in6_addr* LPIN6_ADDR;
|
||||
|
||||
struct sockaddr_in6_old
|
||||
{
|
||||
SHORT sin6_family;
|
||||
USHORT sin6_port;
|
||||
ULONG sin6_flowinfo;
|
||||
IN6_ADDR sin6_addr;
|
||||
};
|
||||
|
||||
typedef union sockaddr_gen
|
||||
{
|
||||
struct sockaddr Address;
|
||||
struct sockaddr_in AddressIn;
|
||||
struct sockaddr_in6_old AddressIn6;
|
||||
} sockaddr_gen;
|
||||
|
||||
#define _IFF_UP 0x00000001
|
||||
#define _IFF_BROADCAST 0x00000002
|
||||
#define _IFF_LOOPBACK 0x00000004
|
||||
#define _IFF_POINTTOPOINT 0x00000008
|
||||
#define _IFF_MULTICAST 0x00000010
|
||||
|
||||
struct _INTERFACE_INFO
|
||||
{
|
||||
ULONG iiFlags;
|
||||
sockaddr_gen iiAddress;
|
||||
sockaddr_gen iiBroadcastAddress;
|
||||
sockaddr_gen iiNetmask;
|
||||
};
|
||||
typedef struct _INTERFACE_INFO INTERFACE_INFO;
|
||||
typedef INTERFACE_INFO* LPINTERFACE_INFO;
|
||||
|
||||
#define MAX_PROTOCOL_CHAIN 7
|
||||
#define WSAPROTOCOL_LEN 255
|
||||
|
||||
typedef struct _WSAPROTOCOLCHAIN
|
||||
{
|
||||
int ChainLen;
|
||||
DWORD ChainEntries[MAX_PROTOCOL_CHAIN];
|
||||
}
|
||||
WSAPROTOCOLCHAIN, *LPWSAPROTOCOLCHAIN;
|
||||
|
||||
typedef struct _WSAPROTOCOL_INFOA
|
||||
{
|
||||
DWORD dwServiceFlags1;
|
||||
DWORD dwServiceFlags2;
|
||||
DWORD dwServiceFlags3;
|
||||
DWORD dwServiceFlags4;
|
||||
DWORD dwProviderFlags;
|
||||
GUID ProviderId;
|
||||
DWORD dwCatalogEntryId;
|
||||
WSAPROTOCOLCHAIN ProtocolChain;
|
||||
int iVersion;
|
||||
int iAddressFamily;
|
||||
int iMaxSockAddr;
|
||||
int iMinSockAddr;
|
||||
int iSocketType;
|
||||
int iProtocol;
|
||||
int iProtocolMaxOffset;
|
||||
int iNetworkByteOrder;
|
||||
int iSecurityScheme;
|
||||
DWORD dwMessageSize;
|
||||
DWORD dwProviderReserved;
|
||||
CHAR szProtocol[WSAPROTOCOL_LEN+1];
|
||||
}
|
||||
WSAPROTOCOL_INFOA, *LPWSAPROTOCOL_INFOA;
|
||||
|
||||
typedef struct _WSAPROTOCOL_INFOW
|
||||
{
|
||||
DWORD dwServiceFlags1;
|
||||
DWORD dwServiceFlags2;
|
||||
DWORD dwServiceFlags3;
|
||||
DWORD dwServiceFlags4;
|
||||
DWORD dwProviderFlags;
|
||||
GUID ProviderId;
|
||||
DWORD dwCatalogEntryId;
|
||||
WSAPROTOCOLCHAIN ProtocolChain;
|
||||
int iVersion;
|
||||
int iAddressFamily;
|
||||
int iMaxSockAddr;
|
||||
int iMinSockAddr;
|
||||
int iSocketType;
|
||||
int iProtocol;
|
||||
int iProtocolMaxOffset;
|
||||
int iNetworkByteOrder;
|
||||
int iSecurityScheme;
|
||||
DWORD dwMessageSize;
|
||||
DWORD dwProviderReserved;
|
||||
WCHAR szProtocol[WSAPROTOCOL_LEN+1];
|
||||
}
|
||||
WSAPROTOCOL_INFOW, *LPWSAPROTOCOL_INFOW;
|
||||
|
||||
typedef void (CALLBACK * LPWSAOVERLAPPED_COMPLETION_ROUTINE)(DWORD dwError,
|
||||
DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags);
|
||||
|
||||
typedef UINT32 GROUP;
|
||||
#define SG_UNCONSTRAINED_GROUP 0x01
|
||||
#define SG_CONSTRAINED_GROUP 0x02
|
||||
|
||||
#define SIO_GET_INTERFACE_LIST _IOR('t', 127, ULONG)
|
||||
#define SIO_GET_INTERFACE_LIST_EX _IOR('t', 126, ULONG)
|
||||
#define SIO_SET_MULTICAST_FILTER _IOW('t', 125, ULONG)
|
||||
#define SIO_GET_MULTICAST_FILTER _IOW('t', 124 | IOC_IN, ULONG)
|
||||
#define SIOCSIPMSFILTER SIO_SET_MULTICAST_FILTER
|
||||
#define SIOCGIPMSFILTER SIO_GET_MULTICAST_FILTER
|
||||
|
||||
#ifdef UNICODE
|
||||
#define WSAPROTOCOL_INFO WSAPROTOCOL_INFOW
|
||||
#define LPWSAPROTOCOL_INFO LPWSAPROTOCOL_INFOW
|
||||
#else
|
||||
#define WSAPROTOCOL_INFO WSAPROTOCOL_INFOA
|
||||
#define LPWSAPROTOCOL_INFO LPWSAPROTOCOL_INFOA
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -175,6 +298,14 @@ WINPR_API int WSAEventSelect(SOCKET s, WSAEVENT hEventObject, LONG lNetworkEvent
|
||||
WINPR_API DWORD WSAWaitForMultipleEvents(DWORD cEvents,
|
||||
const HANDLE* lphEvents, BOOL fWaitAll, DWORD dwTimeout, BOOL fAlertable);
|
||||
|
||||
WINPR_API SOCKET WSASocketA(int af, int type, int protocol, LPWSAPROTOCOL_INFOA lpProtocolInfo, GROUP g, DWORD dwFlags);
|
||||
WINPR_API SOCKET WSASocketW(int af, int type, int protocol, LPWSAPROTOCOL_INFOW lpProtocolInfo, GROUP g, DWORD dwFlags);
|
||||
|
||||
WINPR_API int WSAIoctl(SOCKET s, DWORD dwIoControlCode, LPVOID lpvInBuffer,
|
||||
DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
|
||||
LPDWORD lpcbBytesReturned, LPWSAOVERLAPPED lpOverlapped,
|
||||
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
|
||||
|
||||
WINPR_API SOCKET _accept(SOCKET s, struct sockaddr* addr, int* addrlen);
|
||||
WINPR_API int _bind(SOCKET s, const struct sockaddr* addr, int namelen);
|
||||
WINPR_API int closesocket(SOCKET s);
|
||||
@ -210,6 +341,12 @@ WINPR_API struct protoent* _getprotobyname(const char* name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UNICODE
|
||||
#define WSASocket WSASocketW
|
||||
#else
|
||||
#define WSASocket WSASocketA
|
||||
#endif
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#endif /* WINPR_WINSOCK_H */
|
||||
|
@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/thread.h>
|
||||
#include <winpr/interlocked.h>
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
static void *test_thread(void *arg)
|
||||
{
|
||||
long timeout = random();
|
||||
long timeout = rand();
|
||||
timeout %= 1000;
|
||||
timeout += 100;
|
||||
Sleep(timeout);
|
||||
|
@ -650,6 +650,151 @@ DWORD WSAWaitForMultipleEvents(DWORD cEvents, const HANDLE* lphEvents, BOOL fWai
|
||||
return WaitForMultipleObjectsEx(cEvents, lphEvents, fWaitAll, dwTimeout, fAlertable);
|
||||
}
|
||||
|
||||
SOCKET WSASocketA(int af, int type, int protocol, LPWSAPROTOCOL_INFOA lpProtocolInfo, GROUP g, DWORD dwFlags)
|
||||
{
|
||||
SOCKET s;
|
||||
|
||||
s = _socket(af, type, protocol);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
SOCKET WSASocketW(int af, int type, int protocol, LPWSAPROTOCOL_INFOW lpProtocolInfo, GROUP g, DWORD dwFlags)
|
||||
{
|
||||
return WSASocketA(af, type, protocol, (LPWSAPROTOCOL_INFOA) lpProtocolInfo, g, dwFlags);
|
||||
}
|
||||
|
||||
int WSAIoctl(SOCKET s, DWORD dwIoControlCode, LPVOID lpvInBuffer,
|
||||
DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
|
||||
LPDWORD lpcbBytesReturned, LPWSAOVERLAPPED lpOverlapped,
|
||||
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
|
||||
{
|
||||
int fd;
|
||||
int index;
|
||||
ULONG nFlags;
|
||||
size_t offset;
|
||||
size_t ifreq_len;
|
||||
struct ifreq* ifreq;
|
||||
struct ifconf ifconf;
|
||||
char address[128];
|
||||
char broadcast[128];
|
||||
char netmask[128];
|
||||
char buffer[4096];
|
||||
int numInterfaces;
|
||||
int maxNumInterfaces;
|
||||
INTERFACE_INFO* pInterface;
|
||||
INTERFACE_INFO* pInterfaces;
|
||||
struct sockaddr_in* pAddress;
|
||||
struct sockaddr_in* pBroadcast;
|
||||
struct sockaddr_in* pNetmask;
|
||||
|
||||
if ((dwIoControlCode != SIO_GET_INTERFACE_LIST) ||
|
||||
(!lpvOutBuffer || !cbOutBuffer || !lpcbBytesReturned))
|
||||
{
|
||||
WSASetLastError(WSAEINVAL);
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
fd = (int) s;
|
||||
pInterfaces = (INTERFACE_INFO*) lpvOutBuffer;
|
||||
maxNumInterfaces = cbOutBuffer / sizeof(INTERFACE_INFO);
|
||||
|
||||
ifconf.ifc_len = sizeof(buffer);
|
||||
ifconf.ifc_buf = buffer;
|
||||
|
||||
if (ioctl(fd, SIOCGIFCONF, &ifconf) != 0)
|
||||
{
|
||||
WSASetLastError(WSAENETDOWN);
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
offset = 0;
|
||||
numInterfaces = 0;
|
||||
ifreq = ifconf.ifc_req;
|
||||
|
||||
while ((offset < ifconf.ifc_len) && (numInterfaces < maxNumInterfaces))
|
||||
{
|
||||
pInterface = &pInterfaces[index];
|
||||
pAddress = (struct sockaddr_in*) &pInterface->iiAddress;
|
||||
pBroadcast = (struct sockaddr_in*) &pInterface->iiBroadcastAddress;
|
||||
pNetmask = (struct sockaddr_in*) &pInterface->iiNetmask;
|
||||
|
||||
if (ioctl(fd, SIOCGIFFLAGS, ifreq) != 0)
|
||||
goto next_ifreq;
|
||||
|
||||
nFlags = 0;
|
||||
|
||||
if (ifreq->ifr_flags & IFF_UP)
|
||||
nFlags |= _IFF_UP;
|
||||
|
||||
if (ifreq->ifr_flags & IFF_BROADCAST)
|
||||
nFlags |= _IFF_BROADCAST;
|
||||
|
||||
if (ifreq->ifr_flags & IFF_LOOPBACK)
|
||||
nFlags |= _IFF_LOOPBACK;
|
||||
|
||||
if (ifreq->ifr_flags & IFF_POINTOPOINT)
|
||||
nFlags |= _IFF_POINTTOPOINT;
|
||||
|
||||
if (ifreq->ifr_flags & IFF_MULTICAST)
|
||||
nFlags |= _IFF_MULTICAST;
|
||||
|
||||
pInterface->iiFlags = nFlags;
|
||||
|
||||
if (ioctl(fd, SIOCGIFADDR, ifreq) != 0)
|
||||
goto next_ifreq;
|
||||
|
||||
if ((ifreq->ifr_addr.sa_family != AF_INET) && (ifreq->ifr_addr.sa_family != AF_INET6))
|
||||
goto next_ifreq;
|
||||
|
||||
getnameinfo(&ifreq->ifr_addr, sizeof(ifreq->ifr_addr),
|
||||
address, sizeof(address), 0, 0, NI_NUMERICHOST);
|
||||
|
||||
inet_pton(ifreq->ifr_addr.sa_family, address, (void*) &pAddress->sin_addr);
|
||||
|
||||
if (ioctl(fd, SIOCGIFBRDADDR, ifreq) != 0)
|
||||
goto next_ifreq;
|
||||
|
||||
if ((ifreq->ifr_addr.sa_family != AF_INET) && (ifreq->ifr_addr.sa_family != AF_INET6))
|
||||
goto next_ifreq;
|
||||
|
||||
getnameinfo(&ifreq->ifr_addr, sizeof(ifreq->ifr_addr),
|
||||
broadcast, sizeof(broadcast), 0, 0, NI_NUMERICHOST);
|
||||
|
||||
inet_pton(ifreq->ifr_addr.sa_family, broadcast, (void*) &pBroadcast->sin_addr);
|
||||
|
||||
if (ioctl(fd, SIOCGIFNETMASK, ifreq) != 0)
|
||||
goto next_ifreq;
|
||||
|
||||
if ((ifreq->ifr_addr.sa_family != AF_INET) && (ifreq->ifr_addr.sa_family != AF_INET6))
|
||||
goto next_ifreq;
|
||||
|
||||
getnameinfo(&ifreq->ifr_addr, sizeof(ifreq->ifr_addr),
|
||||
netmask, sizeof(netmask), 0, 0, NI_NUMERICHOST);
|
||||
|
||||
inet_pton(ifreq->ifr_addr.sa_family, netmask, (void*) &pNetmask->sin_addr);
|
||||
|
||||
numInterfaces++;
|
||||
|
||||
next_ifreq:
|
||||
|
||||
#ifndef __linux__
|
||||
ifreq_len = IFNAMSIZ + ifreq->ifr_addr.sa_len;
|
||||
#else
|
||||
ifreq_len = sizeof(*ifreq);
|
||||
#endif
|
||||
|
||||
ifreq = (struct ifreq*) &((BYTE*) ifreq)[ifreq_len];
|
||||
offset += ifreq_len;
|
||||
index++;
|
||||
}
|
||||
|
||||
*lpcbBytesReturned = (DWORD) (numInterfaces * sizeof(INTERFACE_INFO));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SOCKET _accept(SOCKET s, struct sockaddr* addr, int* addrlen)
|
||||
{
|
||||
int status;
|
||||
|
Loading…
x
Reference in New Issue
Block a user