| 215 | } |
| 216 | |
| 217 | int icmp_query(icmp_handle handle, const char *ip, uint32_t *timems) |
| 218 | { |
| 219 | assert(wsa_initialized); |
| 220 | assert(ip); |
| 221 | assert(timems); |
| 222 | auto h = socket_fd(handle); |
| 223 | |
| 224 | LPHOSTENT lpHost = gethostbyname(ip); |
| 225 | if (lpHost != nullptr) |
| 226 | { |
| 227 | sockaddr_in destAddress; |
| 228 | destAddress.sin_addr.s_addr = ((in_addr *)lpHost->h_addr_list[0])->s_addr; |
| 229 | destAddress.sin_family = AF_INET; |
| 230 | destAddress.sin_port = 0; |
| 231 | |
| 232 | const int ICMP_ECHOREQ = 8; |
| 233 | ECHOREQUEST request = {}; |
| 234 | request.icmpHdr.Type = ICMP_ECHOREQ; |
| 235 | request.dwTime = *timems; |
| 236 | memset(request.cData, 80, sizeof(request.cData)); |
| 237 | |
| 238 | const auto rs = sizeof(ECHOREQUEST); |
| 239 | request.icmpHdr.Checksum = icmp_checksum((uint16_t *)&request, rs); |
| 240 | |
| 241 | const auto r = (LPSTR)&request; |
| 242 | const auto dst = (LPSOCKADDR)&destAddress; |
| 243 | ::sendto(h, r, rs, 0, dst, sizeof(SOCKADDR_IN)); |
| 244 | |
| 245 | timeval timeoutInfo; |
| 246 | fd_set readfds; |
| 247 | FD_ZERO(&readfds); |
| 248 | FD_SET(h, &readfds); |
| 249 | timeoutInfo.tv_sec = 1; |
| 250 | timeoutInfo.tv_usec = 0; |
| 251 | |
| 252 | if (::select(1, &readfds, nullptr, nullptr, &timeoutInfo)) |
| 253 | { |
| 254 | ECHOREPLY answer; |
| 255 | sockaddr_in sourceAddress; |
| 256 | int length = sizeof(sockaddr_in); |
| 257 | |
| 258 | const auto a = (LPSTR)&answer; |
| 259 | const auto as = sizeof(ECHOREPLY); |
| 260 | const auto src = (LPSOCKADDR)&sourceAddress; |
| 261 | if (::recvfrom(h, a, as, 0, src, &length) != -1) |
| 262 | { |
| 263 | *timems = answer.echoRequest.dwTime; |
| 264 | return 0; |
| 265 | } |
| 266 | else |
| 267 | return -1; |
| 268 | } |
| 269 | return -2; |
| 270 | } |
| 271 | return -3; |
| 272 | } |
| 273 | |
| 274 | void icmp_close(icmp_handle handle) |
no test coverage detected