1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - TCP layer
4 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
5 Copyright 2005-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
6 Copyright 2012-2013 Henrik Andersson <hean01@cendio.se> for Cendio AB
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
30 #define TCP_CLOSE(_sck) closesocket(_sck)
31 #define TCP_STRERROR "tcp error"
32 #define TCP_SLEEP(_n) Sleep(_n)
33 #define TCP_BLOCKS (WSAGetLastError() == WSAEWOULDBLOCK)
35 #define TCP_CLOSE(_sck) close(_sck)
36 #define TCP_STRERROR strerror(errno)
37 #define TCP_SLEEP(_n) sleep(_n)
38 #define TCP_BLOCKS (errno == EWOULDBLOCK)
42 #define INADDR_NONE ((unsigned long) -1)
46 #define STREAM_COUNT 8
48 #define STREAM_COUNT 1
55 SecPkgContext_StreamSizes ssl_sizes
;
64 static char * g_ssl_server
= NULL
;
65 static RD_BOOL g_ssl_initialized
= False
;
66 static RD_BOOL cred_handle_initialized
= False
;
67 static RD_BOOL have_compat_cred_handle
= False
;
68 static SecHandle cred_handle
, compat_cred_handle
;
69 static netconn_t g_ssl1
;
70 static netconn_t
*g_ssl
= NULL
;
73 static struct stream g_in
;
74 static struct stream g_out
[STREAM_COUNT
];
75 int g_tcp_port_rdp
= TCP_PORT_RDP
;
76 extern RD_BOOL g_user_quit
;
77 extern RD_BOOL g_network_error
;
78 extern RD_BOOL g_reconnect_loop
;
80 /* Initialise TCP transport data packet */
82 tcp_init(uint32 maxlen
)
84 static int cur_stream_id
= 0;
88 scard_lock(SCARD_LOCK_TCP
);
90 result
= &g_out
[cur_stream_id
];
91 cur_stream_id
= (cur_stream_id
+ 1) % STREAM_COUNT
;
93 if (maxlen
> result
->size
)
95 result
->data
= (uint8
*) xrealloc(result
->data
, maxlen
);
96 result
->size
= maxlen
;
99 result
->p
= result
->data
;
100 result
->end
= result
->data
+ result
->size
;
102 scard_unlock(SCARD_LOCK_TCP
);
109 RD_BOOL
send_ssl_chunk(const void *msg
, size_t size
)
111 SecBuffer bufs
[4] = {
112 {g_ssl
->ssl_sizes
.cbHeader
, SECBUFFER_STREAM_HEADER
, g_ssl
->ssl_buf
},
113 {size
, SECBUFFER_DATA
, g_ssl
->ssl_buf
+g_ssl
->ssl_sizes
.cbHeader
},
114 {g_ssl
->ssl_sizes
.cbTrailer
, SECBUFFER_STREAM_TRAILER
, g_ssl
->ssl_buf
+g_ssl
->ssl_sizes
.cbHeader
+size
},
115 {0, SECBUFFER_EMPTY
, NULL
}
117 SecBufferDesc buf_desc
= {SECBUFFER_VERSION
, sizeof(bufs
)/sizeof(*bufs
), bufs
};
121 memcpy(bufs
[1].pvBuffer
, msg
, size
);
122 res
= EncryptMessage(&g_ssl
->ssl_ctx
, 0, &buf_desc
, 0);
125 error("EncryptMessage failed: %d\n", res
);
129 tcp_res
= send(g_sock
, g_ssl
->ssl_buf
, bufs
[0].cbBuffer
+bufs
[1].cbBuffer
+bufs
[2].cbBuffer
, 0);
132 error("send failed: %d (%s)\n", tcp_res
, TCP_STRERROR
);
139 DWORD
read_ssl_chunk(void *buf
, SIZE_T buf_size
, BOOL blocking
, SIZE_T
*ret_size
, BOOL
*eof
)
141 const SIZE_T ssl_buf_size
= g_ssl
->ssl_sizes
.cbHeader
+g_ssl
->ssl_sizes
.cbMaximumMessage
+g_ssl
->ssl_sizes
.cbTrailer
;
143 SecBufferDesc buf_desc
= {SECBUFFER_VERSION
, sizeof(bufs
)/sizeof(*bufs
), bufs
};
144 SSIZE_T size
, buf_len
= 0;
148 //assert(conn->extra_len < ssl_buf_size);
150 if (g_ssl
->extra_len
)
152 memcpy(g_ssl
->ssl_buf
, g_ssl
->extra_buf
, g_ssl
->extra_len
);
153 buf_len
= g_ssl
->extra_len
;
154 g_ssl
->extra_len
= 0;
155 xfree(g_ssl
->extra_buf
);
156 g_ssl
->extra_buf
= NULL
;
159 size
= recv(g_sock
, g_ssl
->ssl_buf
+buf_len
, ssl_buf_size
-buf_len
, 0);
164 if (size
== -1 && TCP_BLOCKS
)
166 return WSAEWOULDBLOCK
;
168 error("recv failed: %d (%s)\n", size
, TCP_STRERROR
);
169 return -1;//ERROR_INTERNET_CONNECTION_ABORTED;
181 return ERROR_SUCCESS
;
188 memset(bufs
, 0, sizeof(bufs
));
189 bufs
[0].BufferType
= SECBUFFER_DATA
;
190 bufs
[0].cbBuffer
= buf_len
;
191 bufs
[0].pvBuffer
= g_ssl
->ssl_buf
;
193 res
= DecryptMessage(&g_ssl
->ssl_ctx
, &buf_desc
, 0, NULL
);
198 case SEC_I_CONTEXT_EXPIRED
:
200 return ERROR_SUCCESS
;
201 case SEC_E_INCOMPLETE_MESSAGE
:
202 //assert(buf_len < ssl_buf_size);
204 size
= recv(g_sock
, g_ssl
->ssl_buf
+buf_len
, ssl_buf_size
-buf_len
, 0);
207 if (size
== -1 && TCP_BLOCKS
)
209 /* FIXME: Optimize extra_buf usage. */
210 g_ssl
->extra_buf
= xmalloc(buf_len
);
211 if (!g_ssl
->extra_buf
)
212 return ERROR_NOT_ENOUGH_MEMORY
;
214 g_ssl
->extra_len
= buf_len
;
215 memcpy(g_ssl
->extra_buf
, g_ssl
->ssl_buf
, g_ssl
->extra_len
);
216 return WSAEWOULDBLOCK
;
219 error("recv failed: %d (%s)\n", size
, TCP_STRERROR
);
220 return -1;//ERROR_INTERNET_CONNECTION_ABORTED;
226 error("DecryptMessage failed: %d\n", res
);
227 return -1;//ERROR_INTERNET_CONNECTION_ABORTED;
230 while (res
!= SEC_E_OK
);
232 for (i
=0; i
< sizeof(bufs
)/sizeof(*bufs
); i
++)
234 if (bufs
[i
].BufferType
== SECBUFFER_DATA
)
236 size
= min(buf_size
, bufs
[i
].cbBuffer
);
237 memcpy(buf
, bufs
[i
].pvBuffer
, size
);
238 if (size
< bufs
[i
].cbBuffer
)
240 //assert(!conn->peek_len);
241 g_ssl
->peek_msg_mem
= g_ssl
->peek_msg
= xmalloc(bufs
[i
].cbBuffer
- size
);
242 if (!g_ssl
->peek_msg
)
243 return ERROR_NOT_ENOUGH_MEMORY
;
244 g_ssl
->peek_len
= bufs
[i
].cbBuffer
-size
;
245 memcpy(g_ssl
->peek_msg
, (char*)bufs
[i
].pvBuffer
+size
, g_ssl
->peek_len
);
252 for (i
=0; i
< sizeof(bufs
)/sizeof(*bufs
); i
++)
254 if (bufs
[i
].BufferType
== SECBUFFER_EXTRA
)
256 g_ssl
->extra_buf
= xmalloc(bufs
[i
].cbBuffer
);
257 if (!g_ssl
->extra_buf
)
258 return ERROR_NOT_ENOUGH_MEMORY
;
260 g_ssl
->extra_len
= bufs
[i
].cbBuffer
;
261 memcpy(g_ssl
->extra_buf
, bufs
[i
].pvBuffer
, g_ssl
->extra_len
);
265 return ERROR_SUCCESS
;
267 #endif /* WITH_SSL */
268 /* Send TCP transport data packet */
272 int length
= s
->end
- s
->data
;
275 if (g_network_error
== True
)
279 scard_lock(SCARD_LOCK_TCP
);
281 while (total
< length
)
286 const BYTE
*ptr
= s
->data
+ total
;
291 while (length
- total
)
293 chunk_size
= min(length
- total
, g_ssl
->ssl_sizes
.cbMaximumMessage
);
294 if (!send_ssl_chunk(ptr
, chunk_size
))
297 scard_unlock(SCARD_LOCK_TCP
);
300 //error("send_ssl_chunk: %d (%s)\n", sent, TCP_STRERROR);
301 g_network_error
= True
;
307 length
-= chunk_size
;
312 #endif /* WITH_SSL */
313 sent
= send(g_sock
, (const char *)s
->data
+ total
, length
- total
, 0);
316 if (sent
== -1 && TCP_BLOCKS
)
324 scard_unlock(SCARD_LOCK_TCP
);
327 error("send: %d (%s)\n", sent
, TCP_STRERROR
);
328 g_network_error
= True
;
334 #endif /* WITH_SSL */
338 scard_unlock(SCARD_LOCK_TCP
);
342 /* Receive a message on the TCP layer */
344 tcp_recv(STREAM s
, uint32 length
)
346 uint32 new_length
, end_offset
, p_offset
;
349 if (g_network_error
== True
)
354 /* read into "new" stream */
355 if (length
> g_in
.size
)
357 g_in
.data
= (uint8
*) xrealloc(g_in
.data
, length
);
360 g_in
.end
= g_in
.p
= g_in
.data
;
365 /* append to existing stream */
366 new_length
= (s
->end
- s
->data
) + length
;
367 if (new_length
> s
->size
)
369 p_offset
= s
->p
- s
->data
;
370 end_offset
= s
->end
- s
->data
;
371 s
->data
= (uint8
*) xrealloc(s
->data
, new_length
);
372 s
->size
= new_length
;
373 s
->p
= s
->data
+ p_offset
;
374 s
->end
= s
->data
+ end_offset
;
382 #endif /* WITH_SSL */
384 if (!ui_select(g_sock
))
401 size
= min(length
, g_ssl
->peek_len
);
402 memcpy(s
->end
, g_ssl
->peek_msg
, size
);
403 g_ssl
->peek_len
-= size
;
404 g_ssl
->peek_msg
+= size
;
407 if (!g_ssl
->peek_len
)
409 xfree(g_ssl
->peek_msg_mem
);
410 g_ssl
->peek_msg_mem
= g_ssl
->peek_msg
= NULL
;
418 res
= read_ssl_chunk((BYTE
*)s
->end
, length
, TRUE
, &size
, &eof
);
419 if (res
!= ERROR_SUCCESS
)
421 if (res
== WSAEWOULDBLOCK
)
430 error("read_ssl_chunk: %d (%s)\n", res
, TCP_STRERROR
);
431 g_network_error
= True
;
437 while (!size
&& !eof
);
442 #endif /* WITH_SSL */
443 rcvd
= recv(g_sock
, (char *)s
->end
, length
, 0);
446 if (rcvd
== -1 && TCP_BLOCKS
)
452 error("recv: %d (%s)\n", rcvd
, TCP_STRERROR
);
453 g_network_error
= True
;
459 error("Connection closed\n");
464 #endif /* WITH_SSL */
476 ensure_cred_handle(void)
478 SECURITY_STATUS res
= SEC_E_OK
;
480 if (!cred_handle_initialized
)
482 SCHANNEL_CRED cred
= {SCHANNEL_CRED_VERSION
};
483 SecPkgCred_SupportedProtocols prots
;
485 res
= AcquireCredentialsHandleW(NULL
, (WCHAR
*)UNISP_NAME_W
, SECPKG_CRED_OUTBOUND
, NULL
, &cred
,
486 NULL
, NULL
, &cred_handle
, NULL
);
489 res
= QueryCredentialsAttributesA(&cred_handle
, SECPKG_ATTR_SUPPORTED_PROTOCOLS
, &prots
);
490 if (res
!= SEC_E_OK
|| (prots
.grbitProtocol
& SP_PROT_TLS1_1PLUS_CLIENT
))
492 cred
.grbitEnabledProtocols
= prots
.grbitProtocol
& ~SP_PROT_TLS1_1PLUS_CLIENT
;
493 res
= AcquireCredentialsHandleW(NULL
, (WCHAR
*)UNISP_NAME_W
, SECPKG_CRED_OUTBOUND
, NULL
, &cred
,
494 NULL
, NULL
, &compat_cred_handle
, NULL
);
495 have_compat_cred_handle
= res
== SEC_E_OK
;
499 cred_handle_initialized
= res
== SEC_E_OK
;
504 error("ensure_cred_handle failed: %ld\n", res
);
512 ssl_handshake(RD_BOOL compat_mode
)
514 SecBuffer out_buf
= {0, SECBUFFER_TOKEN
, NULL
}, in_bufs
[2] = {{0, SECBUFFER_TOKEN
}, {0, SECBUFFER_EMPTY
}};
515 SecBufferDesc out_desc
= {SECBUFFER_VERSION
, 1, &out_buf
}, in_desc
= {SECBUFFER_VERSION
, 2, in_bufs
};
516 SecHandle
*cred
= &cred_handle
;
518 SIZE_T read_buf_size
= 2048;
522 SECURITY_STATUS status
;
523 DWORD res
= ERROR_SUCCESS
;
525 const DWORD isc_req_flags
= ISC_REQ_ALLOCATE_MEMORY
|ISC_REQ_USE_SESSION_KEY
|ISC_REQ_CONFIDENTIALITY
526 |ISC_REQ_SEQUENCE_DETECT
|ISC_REQ_REPLAY_DETECT
|ISC_REQ_MANUAL_CRED_VALIDATION
;
528 if (!ensure_cred_handle())
532 if (!have_compat_cred_handle
)
534 cred
= &compat_cred_handle
;
537 read_buf
= xmalloc(read_buf_size
);
539 return ERROR_OUTOFMEMORY
;
544 status
= InitializeSecurityContextA(cred
, NULL
, g_ssl_server
, isc_req_flags
, 0, 0, NULL
, 0,
545 &ctx
, &out_desc
, &attrs
, NULL
);
547 //assert(status != SEC_E_OK);
549 while (status
== SEC_I_CONTINUE_NEEDED
|| status
== SEC_E_INCOMPLETE_MESSAGE
)
551 if (out_buf
.cbBuffer
)
553 //assert(status == SEC_I_CONTINUE_NEEDED);
555 size
= send(g_sock
, out_buf
.pvBuffer
, out_buf
.cbBuffer
, 0);
556 if (size
!= out_buf
.cbBuffer
)
558 error("send failed: %d (%s)\n", size
, TCP_STRERROR
);
563 FreeContextBuffer(out_buf
.pvBuffer
);
564 out_buf
.pvBuffer
= NULL
;
565 out_buf
.cbBuffer
= 0;
568 if (status
== SEC_I_CONTINUE_NEEDED
)
570 //assert(in_bufs[1].cbBuffer < read_buf_size);
572 memmove(read_buf
, (BYTE
*)in_bufs
[0].pvBuffer
+in_bufs
[0].cbBuffer
-in_bufs
[1].cbBuffer
, in_bufs
[1].cbBuffer
);
573 in_bufs
[0].cbBuffer
= in_bufs
[1].cbBuffer
;
575 in_bufs
[1].BufferType
= SECBUFFER_EMPTY
;
576 in_bufs
[1].cbBuffer
= 0;
577 in_bufs
[1].pvBuffer
= NULL
;
580 //assert(in_bufs[0].BufferType == SECBUFFER_TOKEN);
581 //assert(in_bufs[1].BufferType == SECBUFFER_EMPTY);
583 if (in_bufs
[0].cbBuffer
+ 1024 > read_buf_size
)
585 BYTE
*new_read_buf
= xrealloc(read_buf
, read_buf_size
+ 1024);
588 status
= E_OUTOFMEMORY
;
592 in_bufs
[0].pvBuffer
= read_buf
= new_read_buf
;
593 read_buf_size
+= 1024;
596 size
= recv(g_sock
, (char *)read_buf
+ in_bufs
[0].cbBuffer
, read_buf_size
- in_bufs
[0].cbBuffer
, 0);
599 error("recv failed: %d (%s)\n", size
, TCP_STRERROR
);
604 in_bufs
[0].cbBuffer
+= size
;
605 in_bufs
[0].pvBuffer
= read_buf
;
606 status
= InitializeSecurityContextA(cred
, &ctx
, g_ssl_server
, isc_req_flags
, 0, 0, &in_desc
,
607 0, NULL
, &out_desc
, &attrs
, NULL
);
609 if (status
== SEC_E_OK
) {
610 if (SecIsValidHandle(&g_ssl
->ssl_ctx
))
611 DeleteSecurityContext(&g_ssl
->ssl_ctx
);
612 g_ssl
->ssl_ctx
= ctx
;
614 if (in_bufs
[1].BufferType
== SECBUFFER_EXTRA
)
616 //FIXME("SECBUFFER_EXTRA not supported\n");
619 status
= QueryContextAttributesW(&ctx
, SECPKG_ATTR_STREAM_SIZES
, &g_ssl
->ssl_sizes
);
620 if (status
!= SEC_E_OK
)
622 //error("Can't determine ssl buffer sizes: %ld\n", status);
626 g_ssl
->ssl_buf
= xmalloc(g_ssl
->ssl_sizes
.cbHeader
+ g_ssl
->ssl_sizes
.cbMaximumMessage
627 + g_ssl
->ssl_sizes
.cbTrailer
);
630 res
= GetLastError();
638 if (status
!= SEC_E_OK
|| res
!= ERROR_SUCCESS
)
640 error("Failed to establish SSL connection: %08x (%u)\n", status
, res
);
641 xfree(g_ssl
->ssl_buf
);
642 g_ssl
->ssl_buf
= NULL
;
643 return res
? res
: -1;
646 return ERROR_SUCCESS
;
649 /* Establish a SSL/TLS 1.0 connection */
651 tcp_tls_connect(void)
654 char tcp_port_rdp_s
[10];
656 if (!g_ssl_initialized
)
659 SecInvalidateHandle(&g_ssl
->ssl_ctx
);
661 g_ssl_initialized
= True
;
664 snprintf(tcp_port_rdp_s
, 10, "%d", g_tcp_port_rdp
);
665 if ((err
= ssl_handshake(FALSE
)) != 0)
677 /* Get public key from server of TLS 1.0 connection */
679 tcp_tls_get_server_pubkey(STREAM s
)
681 const CERT_CONTEXT
*cert
= NULL
;
682 SECURITY_STATUS status
;
684 s
->data
= s
->p
= NULL
;
689 status
= QueryContextAttributesW(&g_ssl
->ssl_ctx
, SECPKG_ATTR_REMOTE_CERT_CONTEXT
, (void*)&cert
);
690 if (status
!= SEC_E_OK
)
692 error("tcp_tls_get_server_pubkey: QueryContextAttributesW() failed %ld\n", status
);
696 s
->size
= cert
->cbCertEncoded
;
699 error("tcp_tls_get_server_pubkey: cert->cbCertEncoded = %ld\n", cert
->cbCertEncoded
);
703 s
->data
= s
->p
= (unsigned char *)xmalloc(s
->size
);
704 memcpy(cert
->pbCertEncoded
, &s
->p
, s
->size
);
706 s
->end
= s
->p
+ s
->size
;
710 CertFreeCertificateContext(cert
);
711 return (s
->size
!= 0);
713 #endif /* WITH_SSL */
715 /* Establish a connection on the TCP layer */
717 tcp_connect(char *server
)
719 socklen_t option_len
;
726 struct addrinfo hints
, *res
, *ressave
;
727 char tcp_port_rdp_s
[10];
729 snprintf(tcp_port_rdp_s
, 10, "%d", g_tcp_port_rdp
);
731 memset(&hints
, 0, sizeof(struct addrinfo
));
732 hints
.ai_family
= AF_UNSPEC
;
733 hints
.ai_socktype
= SOCK_STREAM
;
735 if ((n
= getaddrinfo(server
, tcp_port_rdp_s
, &hints
, &res
)))
737 error("getaddrinfo: %s\n", gai_strerror(n
));
745 g_sock
= socket(res
->ai_family
, res
->ai_socktype
, res
->ai_protocol
);
748 if (connect(g_sock
, res
->ai_addr
, res
->ai_addrlen
) == 0)
755 freeaddrinfo(ressave
);
759 error("%s: unable to connect\n", server
);
763 #else /* no IPv6 support */
765 struct hostent
*nslookup
;
766 struct sockaddr_in servaddr
;
768 if ((nslookup
= gethostbyname(server
)) != NULL
)
770 memcpy(&servaddr
.sin_addr
, nslookup
->h_addr
, sizeof(servaddr
.sin_addr
));
772 else if ((servaddr
.sin_addr
.s_addr
= inet_addr(server
)) == INADDR_NONE
)
774 error("%s: unable to resolve host\n", server
);
778 if ((g_sock
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0)
780 error("socket: %s\n", TCP_STRERROR
);
784 servaddr
.sin_family
= AF_INET
;
785 servaddr
.sin_port
= htons((uint16
) g_tcp_port_rdp
);
787 if (connect(g_sock
, (struct sockaddr
*) &servaddr
, sizeof(struct sockaddr
)) < 0)
789 if (!g_reconnect_loop
)
790 error("connect: %s\n", TCP_STRERROR
);
800 option_len
= sizeof(option_value
);
801 setsockopt(g_sock
, IPPROTO_TCP
, TCP_NODELAY
, (void *) &option_value
, option_len
);
802 /* receive buffer must be a least 16 K */
803 if (getsockopt(g_sock
, SOL_SOCKET
, SO_RCVBUF
, (void *) &option_value
, &option_len
) == 0)
805 if (option_value
< (1024 * 16))
807 option_value
= 1024 * 16;
808 option_len
= sizeof(option_value
);
809 setsockopt(g_sock
, SOL_SOCKET
, SO_RCVBUF
, (void *) &option_value
,
815 g_in
.data
= (uint8
*) xmalloc(g_in
.size
);
817 for (i
= 0; i
< STREAM_COUNT
; i
++)
819 g_out
[i
].size
= 4096;
820 g_out
[i
].data
= (uint8
*) xmalloc(g_out
[i
].size
);
824 g_ssl_server
= xmalloc(strlen(server
)+1);
825 #endif /* WITH_SSL */
830 /* Disconnect on the TCP layer */
837 xfree(g_ssl
->peek_msg_mem
);
838 g_ssl
->peek_msg_mem
= NULL
;
839 g_ssl
->peek_msg
= NULL
;
841 xfree(g_ssl
->ssl_buf
);
842 g_ssl
->ssl_buf
= NULL
;
843 xfree(g_ssl
->extra_buf
);
844 g_ssl
->extra_buf
= NULL
;
845 g_ssl
->extra_len
= 0;
846 if (SecIsValidHandle(&g_ssl
->ssl_ctx
))
847 DeleteSecurityContext(&g_ssl
->ssl_ctx
);
848 if (cred_handle_initialized
)
849 FreeCredentialsHandle(&cred_handle
);
850 if (have_compat_cred_handle
)
851 FreeCredentialsHandle(&compat_cred_handle
);
858 g_ssl_initialized
= False
;
860 #endif /* WITH_SSL */
868 static char ipaddr
[32];
869 struct sockaddr_in sockaddr
;
870 socklen_t len
= sizeof(sockaddr
);
871 if (getsockname(g_sock
, (struct sockaddr
*) &sockaddr
, &len
) == 0)
873 uint8
*ip
= (uint8
*) & sockaddr
.sin_addr
;
874 sprintf(ipaddr
, "%d.%d.%d.%d", ip
[0], ip
[1], ip
[2], ip
[3]);
877 strcpy(ipaddr
, "127.0.0.1");
884 struct sockaddr_in sockaddr
;
885 socklen_t len
= sizeof(sockaddr
);
886 if (getpeername(g_sock
, (struct sockaddr
*) &sockaddr
, &len
))
891 /* reset the state of the tcp layer */
892 /* Support for Session Directory */
894 tcp_reset_state(void)
898 /* Clear the incoming stream */
899 if (g_in
.data
!= NULL
)
909 g_in
.channel_hdr
= NULL
;
911 /* Clear the outgoing stream(s) */
912 for (i
= 0; i
< STREAM_COUNT
; i
++)
914 if (g_out
[i
].data
!= NULL
)
915 xfree(g_out
[i
].data
);
918 g_out
[i
].data
= NULL
;
920 g_out
[i
].iso_hdr
= NULL
;
921 g_out
[i
].mcs_hdr
= NULL
;
922 g_out
[i
].sec_hdr
= NULL
;
923 g_out
[i
].rdp_hdr
= NULL
;
924 g_out
[i
].channel_hdr
= NULL
;