Open lochv opened 4 years ago
@andybons hi,
it seems SIO_RCVALL flag wasn't set, so only recv when network adapter just re-enabled. https://github.com/golang/net/search?q=RCVALL&unscoped_q=RCVALL
@alexbrainman
@lochv I don't know anything about icmp. I don't want to confuse you.
Alex
@alexbrainman the problem isn't icmp, problem 1: in windows, socket need set SIO_RCVALL flag to monitor raw sock (linux didn't). problem 2: in windows, socket bind on 0.0.0.0 canot set SIO_RCVALL flag. so
icmp.ListenPacket("ip4:icmp", "0.0.0.0")
will not work in windows.
Need to port this example code from C to Go for icmp.ListenPacket work in windows
int F() { WSADATA wsd; char hostname[100]; struct hostent* local; struct in_addr addr; if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) { return 0; } SOCKET RecvSockets[20]; ZeroMemory(&RecvSockets, sizeof(RecvSockets)); gethostname(hostname, sizeof(hostname)); local = gethostbyname(hostname); struct sockaddr_in RecvAddr; fd_set readfds; char *RecvBuf; RecvBuf = (char*)malloc(1024*sizeof(char)); int BufLen = 1024; int iResult; struct sockaddr_in SenderAddr; int SenderAddrSize = sizeof(SenderAddr); // need listen on all interfaces one by one for (int i = 0; local->h_addr_list[i] != 0; i++) { DWORD flag = RCVALL_ON; memcpy(&addr, local->h_addr_list[i], sizeof(struct in_addr)); memcpy(&RecvAddr.sin_addr.s_addr, local->h_addr_list[i], sizeof(RecvAddr.sin_addr.s_addr)); RecvAddr.sin_family = AF_INET; RecvAddr.sin_port = htons(0); RecvSockets[i] = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); bind(RecvSockets[i], (SOCKADDR*)&RecvAddr, sizeof(RecvAddr)); ioctlsocket(RecvSockets[i], SIO_RCVALL, &flag); } int activity; WCHAR szAddr[20] = { 0 }; while (1) { FD_ZERO(&readfds); for (int i = 0; local->h_addr_list[i] != 0; i++) { FD_SET(RecvSockets[i], &readfds); } printf("read active"); activity = select(0, &readfds, NULL, NULL, NULL); if (activity == SOCKET_ERROR) { printf("activity"); wprintf(L"recvfrom failed with error %d\n", WSAGetLastError()); } for (int i = 0; local->h_addr_list[i] != 0; i++) { SOCKET s = RecvSockets[i]; if (FD_ISSET(s, &readfds)) { ZeroMemory(RecvBuf, BufLen); iResult = recv(s, RecvBuf, BufLen, 0); if (iResult == SOCKET_ERROR) continue; if (iResult == 0) continue; printf("%d", iResult); } } } }
the problem isn't icmp, problem 1: in windows, socket need set SIO_RCVALL flag to monitor raw sock (linux didn't). problem 2: in windows, socket bind on 0.0.0.0 canot set SIO_RCVALL flag.
@lochv I know nothing about these things. If you want to fix the code, here is how to contribute
https://golang.org/doc/contribute.html
Maybe altogether we can fix the code.
Thank you.
Alex
If anyone is still interesting in this issue, I managed to somewhat find a fix. Substantial caveat: Receiving ICMP packets from any source only seems to work if the Windows firewall is disabled. 🤷♂️ If someone has more insight into this, I'd appreciate a pointer to more information.
Here is the function that creates the listener that can send and receive ICMP packets from any source. Here is our special (partial) traceroute function using it.
@dhaavi dhaa i think the problem is how to modify "net" package: can listen icmp in windows + keep design pattern
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
I write a func to detect who ping to my computer
What did you expect to see?
fmt.Println(n) every ping.
What did you see instead?
sometime it work, sometime it didn't work. PoC video: https://youtu.be/AyQDH9AQSRc