iphlpapi: Don't use the client buffer in IcmpSendEcho().
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=43252 Signed-off-by: Zhiyi Zhang <zzhang@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
1d2ac5d8b6
commit
417e996e97
|
@ -113,6 +113,9 @@ typedef struct {
|
||||||
#define IP_OPTS_DEFAULT 1
|
#define IP_OPTS_DEFAULT 1
|
||||||
#define IP_OPTS_CUSTOM 2
|
#define IP_OPTS_CUSTOM 2
|
||||||
|
|
||||||
|
#define MAXIPLEN 60
|
||||||
|
#define MAXICMPLEN 76
|
||||||
|
|
||||||
/* The sequence number is unique process wide, so that all threads
|
/* The sequence number is unique process wide, so that all threads
|
||||||
* have a distinct sequence number.
|
* have a distinct sequence number.
|
||||||
*/
|
*/
|
||||||
|
@ -268,15 +271,14 @@ DWORD WINAPI IcmpSendEcho(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
icmp_t* icp=(icmp_t*)IcmpHandle;
|
icmp_t* icp=(icmp_t*)IcmpHandle;
|
||||||
unsigned char* reqbuf;
|
unsigned char *buffer;
|
||||||
int reqsize;
|
int reqsize, repsize;
|
||||||
|
|
||||||
struct icmp_echo_reply* ier;
|
struct icmp_echo_reply* ier;
|
||||||
struct ip* ip_header;
|
struct ip* ip_header;
|
||||||
struct icmp* icmp_header;
|
struct icmp* icmp_header;
|
||||||
char* endbuf;
|
char* endbuf;
|
||||||
int ip_header_len;
|
int ip_header_len;
|
||||||
int maxlen;
|
|
||||||
struct pollfd fdr;
|
struct pollfd fdr;
|
||||||
DWORD send_time,recv_time;
|
DWORD send_time,recv_time;
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
|
@ -306,20 +308,23 @@ DWORD WINAPI IcmpSendEcho(
|
||||||
seq=InterlockedIncrement(&icmp_sequence) & 0xFFFF;
|
seq=InterlockedIncrement(&icmp_sequence) & 0xFFFF;
|
||||||
|
|
||||||
reqsize=ICMP_MINLEN+RequestSize;
|
reqsize=ICMP_MINLEN+RequestSize;
|
||||||
reqbuf=HeapAlloc(GetProcessHeap(), 0, reqsize);
|
/* max ip header + max icmp header and error data + reply size(max 65535 on Windows) */
|
||||||
if (reqbuf==NULL) {
|
/* FIXME: request size of 65535 is not supported yet because max buffer size of raw socket on linux is 32767 */
|
||||||
|
repsize = MAXIPLEN + MAXICMPLEN + min( 65535, ReplySize );
|
||||||
|
buffer = HeapAlloc(GetProcessHeap(), 0, max( repsize, reqsize ));
|
||||||
|
if (buffer == NULL) {
|
||||||
SetLastError(ERROR_OUTOFMEMORY);
|
SetLastError(ERROR_OUTOFMEMORY);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
icmp_header=(struct icmp*)reqbuf;
|
icmp_header=(struct icmp*)buffer;
|
||||||
icmp_header->icmp_type=ICMP_ECHO;
|
icmp_header->icmp_type=ICMP_ECHO;
|
||||||
icmp_header->icmp_code=0;
|
icmp_header->icmp_code=0;
|
||||||
icmp_header->icmp_cksum=0;
|
icmp_header->icmp_cksum=0;
|
||||||
icmp_header->icmp_id=id;
|
icmp_header->icmp_id=id;
|
||||||
icmp_header->icmp_seq=seq;
|
icmp_header->icmp_seq=seq;
|
||||||
memcpy(reqbuf+ICMP_MINLEN, RequestData, RequestSize);
|
memcpy(buffer+ICMP_MINLEN, RequestData, RequestSize);
|
||||||
icmp_header->icmp_cksum=cksum=in_cksum((u_short*)reqbuf,reqsize);
|
icmp_header->icmp_cksum=cksum=in_cksum((u_short*)buffer,reqsize);
|
||||||
|
|
||||||
addr.sin_family=AF_INET;
|
addr.sin_family=AF_INET;
|
||||||
addr.sin_addr.s_addr=DestinationAddress;
|
addr.sin_addr.s_addr=DestinationAddress;
|
||||||
|
@ -367,26 +372,22 @@ DWORD WINAPI IcmpSendEcho(
|
||||||
fdr.events = POLLIN;
|
fdr.events = POLLIN;
|
||||||
addrlen=sizeof(addr);
|
addrlen=sizeof(addr);
|
||||||
ier=ReplyBuffer;
|
ier=ReplyBuffer;
|
||||||
ip_header=(struct ip *) ((char *) ReplyBuffer+sizeof(ICMP_ECHO_REPLY));
|
|
||||||
endbuf=(char *) ReplyBuffer+ReplySize;
|
endbuf=(char *) ReplyBuffer+ReplySize;
|
||||||
maxlen=ReplySize-sizeof(ICMP_ECHO_REPLY);
|
|
||||||
|
|
||||||
/* Send the packet */
|
/* Send the packet */
|
||||||
TRACE("Sending %d bytes (RequestSize=%d) to %s\n", reqsize, RequestSize, inet_ntoa(addr.sin_addr));
|
TRACE("Sending %d bytes (RequestSize=%d) to %s\n", reqsize, RequestSize, inet_ntoa(addr.sin_addr));
|
||||||
#if 0
|
#if 0
|
||||||
if (TRACE_ON(icmp)){
|
if (TRACE_ON(icmp)){
|
||||||
unsigned char* buf=(unsigned char*)reqbuf;
|
|
||||||
int i;
|
int i;
|
||||||
printf("Output buffer:\n");
|
printf("Output buffer:\n");
|
||||||
for (i=0;i<reqsize;i++)
|
for (i=0;i<reqsize;i++)
|
||||||
printf("%2x,", buf[i]);
|
printf("%2x,", buffer[i]);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
send_time = GetTickCount();
|
send_time = GetTickCount();
|
||||||
res=sendto(icp->sid, reqbuf, reqsize, 0, (struct sockaddr*)&addr, sizeof(addr));
|
res=sendto(icp->sid, buffer, reqsize, 0, (struct sockaddr*)&addr, sizeof(addr));
|
||||||
HeapFree(GetProcessHeap (), 0, reqbuf);
|
|
||||||
if (res<0) {
|
if (res<0) {
|
||||||
if (errno==EMSGSIZE)
|
if (errno==EMSGSIZE)
|
||||||
SetLastError(IP_PACKET_TOO_BIG);
|
SetLastError(IP_PACKET_TOO_BIG);
|
||||||
|
@ -403,14 +404,16 @@ DWORD WINAPI IcmpSendEcho(
|
||||||
SetLastError(IP_GENERAL_FAILURE);
|
SetLastError(IP_GENERAL_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
HeapFree(GetProcessHeap(), 0, buffer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the reply */
|
/* Get the reply */
|
||||||
|
ip_header=(struct ip*)buffer;
|
||||||
ip_header_len=0; /* because gcc was complaining */
|
ip_header_len=0; /* because gcc was complaining */
|
||||||
while (poll(&fdr,1,Timeout)>0) {
|
while (poll(&fdr,1,Timeout)>0) {
|
||||||
recv_time = GetTickCount();
|
recv_time = GetTickCount();
|
||||||
res=recvfrom(icp->sid, (char*)ip_header, maxlen, 0, (struct sockaddr*)&addr,&addrlen);
|
res=recvfrom(icp->sid, buffer, repsize, 0, (struct sockaddr*)&addr, &addrlen);
|
||||||
TRACE("received %d bytes from %s\n",res, inet_ntoa(addr.sin_addr));
|
TRACE("received %d bytes from %s\n",res, inet_ntoa(addr.sin_addr));
|
||||||
ier->Status=IP_REQ_TIMED_OUT;
|
ier->Status=IP_REQ_TIMED_OUT;
|
||||||
|
|
||||||
|
@ -508,6 +511,12 @@ DWORD WINAPI IcmpSendEcho(
|
||||||
else Timeout = 0;
|
else Timeout = 0;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
/* Check free space, should be large enough for an ICMP_ECHO_REPLY and remainning icmp data */
|
||||||
|
if (endbuf-(char *)ier < sizeof(struct icmp_echo_reply)+(res-ip_header_len-ICMP_MINLEN)) {
|
||||||
|
res=ier-(ICMP_ECHO_REPLY *)ReplyBuffer;
|
||||||
|
SetLastError(IP_GENERAL_FAILURE);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
/* This is a reply to our packet */
|
/* This is a reply to our packet */
|
||||||
memcpy(&ier->Address,&ip_header->ip_src,sizeof(IPAddr));
|
memcpy(&ier->Address,&ip_header->ip_src,sizeof(IPAddr));
|
||||||
/* Status is already set */
|
/* Status is already set */
|
||||||
|
@ -515,7 +524,7 @@ DWORD WINAPI IcmpSendEcho(
|
||||||
ier->DataSize=res-ip_header_len-ICMP_MINLEN;
|
ier->DataSize=res-ip_header_len-ICMP_MINLEN;
|
||||||
ier->Reserved=0;
|
ier->Reserved=0;
|
||||||
ier->Data=endbuf-ier->DataSize;
|
ier->Data=endbuf-ier->DataSize;
|
||||||
memmove(ier->Data,((char*)ip_header)+ip_header_len+ICMP_MINLEN,ier->DataSize);
|
memcpy(ier->Data, ((char *)ip_header)+ip_header_len+ICMP_MINLEN, ier->DataSize);
|
||||||
ier->Options.Ttl=ip_header->ip_ttl;
|
ier->Options.Ttl=ip_header->ip_ttl;
|
||||||
ier->Options.Tos=ip_header->ip_tos;
|
ier->Options.Tos=ip_header->ip_tos;
|
||||||
ier->Options.Flags=ip_header->ip_off >> 13;
|
ier->Options.Flags=ip_header->ip_off >> 13;
|
||||||
|
@ -523,7 +532,7 @@ DWORD WINAPI IcmpSendEcho(
|
||||||
if (ier->Options.OptionsSize!=0) {
|
if (ier->Options.OptionsSize!=0) {
|
||||||
ier->Options.OptionsData=(unsigned char *) ier->Data-ier->Options.OptionsSize;
|
ier->Options.OptionsData=(unsigned char *) ier->Data-ier->Options.OptionsSize;
|
||||||
/* FIXME: We are supposed to rearrange the option's 'source route' data */
|
/* FIXME: We are supposed to rearrange the option's 'source route' data */
|
||||||
memmove(ier->Options.OptionsData,((char*)ip_header)+ip_header_len,ier->Options.OptionsSize);
|
memcpy(ier->Options.OptionsData, ((char *)ip_header)+ip_header_len, ier->Options.OptionsSize);
|
||||||
endbuf=(char*)ier->Options.OptionsData;
|
endbuf=(char*)ier->Options.OptionsData;
|
||||||
} else {
|
} else {
|
||||||
ier->Options.OptionsData=NULL;
|
ier->Options.OptionsData=NULL;
|
||||||
|
@ -531,9 +540,8 @@ DWORD WINAPI IcmpSendEcho(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare for the next packet */
|
/* Prepare for the next packet */
|
||||||
|
endbuf-=ier->DataSize;
|
||||||
ier++;
|
ier++;
|
||||||
ip_header=(struct ip*)(((char*)ip_header)+sizeof(ICMP_ECHO_REPLY));
|
|
||||||
maxlen=endbuf-(char*)ip_header;
|
|
||||||
|
|
||||||
/* Check out whether there is more but don't wait this time */
|
/* Check out whether there is more but don't wait this time */
|
||||||
Timeout=0;
|
Timeout=0;
|
||||||
|
@ -542,6 +550,8 @@ DWORD WINAPI IcmpSendEcho(
|
||||||
res=ier-(ICMP_ECHO_REPLY*)ReplyBuffer;
|
res=ier-(ICMP_ECHO_REPLY*)ReplyBuffer;
|
||||||
if (res==0)
|
if (res==0)
|
||||||
SetLastError(IP_REQ_TIMED_OUT);
|
SetLastError(IP_REQ_TIMED_OUT);
|
||||||
|
done:
|
||||||
|
HeapFree(GetProcessHeap(), 0, buffer);
|
||||||
TRACE("received %d replies\n",res);
|
TRACE("received %d replies\n",res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -951,6 +951,8 @@ static void testIcmpSendEcho(void)
|
||||||
char senddata[32], replydata[sizeof(senddata) + sizeof(ICMP_ECHO_REPLY)];
|
char senddata[32], replydata[sizeof(senddata) + sizeof(ICMP_ECHO_REPLY)];
|
||||||
DWORD ret, error, replysz = sizeof(replydata);
|
DWORD ret, error, replysz = sizeof(replydata);
|
||||||
IPAddr address;
|
IPAddr address;
|
||||||
|
ICMP_ECHO_REPLY *reply;
|
||||||
|
INT i;
|
||||||
|
|
||||||
if (!pIcmpSendEcho || !pIcmpCreateFile)
|
if (!pIcmpSendEcho || !pIcmpCreateFile)
|
||||||
{
|
{
|
||||||
|
@ -1038,12 +1040,10 @@ todo_wine
|
||||||
replysz = sizeof(replydata) - 1;
|
replysz = sizeof(replydata) - 1;
|
||||||
ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, 1000);
|
ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, 1000);
|
||||||
error = GetLastError();
|
error = GetLastError();
|
||||||
todo_wine {
|
|
||||||
ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
|
ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
|
||||||
ok (error == IP_GENERAL_FAILURE
|
ok (error == IP_GENERAL_FAILURE
|
||||||
|| broken(error == IP_BUF_TOO_SMALL) /* <= 2003 */,
|
|| broken(error == IP_BUF_TOO_SMALL) /* <= 2003 */,
|
||||||
"expected 11050, got %d\n", error);
|
"expected 11050, got %d\n", error);
|
||||||
}
|
|
||||||
|
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
replysz = sizeof(ICMP_ECHO_REPLY);
|
replysz = sizeof(ICMP_ECHO_REPLY);
|
||||||
|
@ -1056,7 +1056,6 @@ todo_wine
|
||||||
replysz = sizeof(ICMP_ECHO_REPLY) + ICMP_MINLEN;
|
replysz = sizeof(ICMP_ECHO_REPLY) + ICMP_MINLEN;
|
||||||
ret = pIcmpSendEcho(icmp, address, senddata, ICMP_MINLEN, NULL, replydata, replysz, 1000);
|
ret = pIcmpSendEcho(icmp, address, senddata, ICMP_MINLEN, NULL, replydata, replysz, 1000);
|
||||||
error = GetLastError();
|
error = GetLastError();
|
||||||
todo_wine
|
|
||||||
ok (ret, "IcmpSendEcho failed unexpectedly with error %d\n", error);
|
ok (ret, "IcmpSendEcho failed unexpectedly with error %d\n", error);
|
||||||
|
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
|
@ -1064,7 +1063,6 @@ todo_wine
|
||||||
ret = pIcmpSendEcho(icmp, address, senddata, ICMP_MINLEN + 1, NULL, replydata, replysz, 1000);
|
ret = pIcmpSendEcho(icmp, address, senddata, ICMP_MINLEN + 1, NULL, replydata, replysz, 1000);
|
||||||
error = GetLastError();
|
error = GetLastError();
|
||||||
ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
|
ok (!ret, "IcmpSendEcho succeeded unexpectedly\n");
|
||||||
todo_wine
|
|
||||||
ok (error == IP_GENERAL_FAILURE
|
ok (error == IP_GENERAL_FAILURE
|
||||||
|| broken(error == IP_BUF_TOO_SMALL) /* <= 2003 */,
|
|| broken(error == IP_BUF_TOO_SMALL) /* <= 2003 */,
|
||||||
"expected 11050, got %d\n", error);
|
"expected 11050, got %d\n", error);
|
||||||
|
@ -1111,6 +1109,21 @@ todo_wine
|
||||||
{
|
{
|
||||||
skip ("Failed to ping with error %d, is lo interface down?.\n", error);
|
skip ("Failed to ping with error %d, is lo interface down?.\n", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check reply data */
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
address = htonl(INADDR_LOOPBACK);
|
||||||
|
for (i = 0; i < ARRAY_SIZE(senddata); i++) senddata[i] = i & 0xff;
|
||||||
|
ret = pIcmpSendEcho(icmp, address, senddata, sizeof(senddata), NULL, replydata, replysz, 1000);
|
||||||
|
error = GetLastError();
|
||||||
|
reply = (ICMP_ECHO_REPLY *)replydata;
|
||||||
|
ok(ret, "IcmpSendEcho failed unexpectedly\n");
|
||||||
|
todo_wine ok(error == NO_ERROR, "Expect last error:0x%08x, got:0x%08x\n", NO_ERROR, error);
|
||||||
|
ok(INADDR_LOOPBACK == ntohl(reply->Address), "Address mismatch, expect:%s, got: %s\n", ntoa(INADDR_LOOPBACK),
|
||||||
|
ntoa(reply->Address));
|
||||||
|
ok(reply->Status == IP_SUCCESS, "Expect status:0x%08x, got:0x%08x\n", IP_SUCCESS, reply->Status);
|
||||||
|
ok(reply->DataSize == sizeof(senddata), "Got size:%d\n", reply->DataSize);
|
||||||
|
ok(!memcmp(senddata, reply->Data, min(sizeof(senddata), reply->DataSize)), "Data mismatch\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue