int icmp_check_replies(char *ipaddress, void **udata) { for(request_list::iterator rit=ping_list.begin();rit!=ping_list.end();rit++) { if(WaitForSingleObject(rit->hEvent,0)==0) //handle is signaled, reply received. { if(IcmpParseReplies(rit->replyBuffer,rit->replyBufferSize)>0) { memcpy(ipaddress,rit->ipaddress,4); ping_list.remove(rit); return 1; //reply received } ResetEvent(rit->hEvent); } if(GetTickCount() >= (rit->sTick+rit->timeOut)) { memcpy(ipaddress,rit->ipaddress,4); *udata = rit->userdata; ping_list.remove(rit); return 2; //timeout } } return 0; }
/* if this next one returns zero, no ping reply. if it returns > 0, ping reply. */ static int internal_do_pingin(struct NetKeepAlive *nka) { int ret = 0; #ifndef WIN32 unsigned char buffer[2048]; fd_set fs; struct timeval tv_sel; memset(buffer, 0, sizeof(buffer)); FD_ZERO(&fs); FD_SET(nka->keepalive_fd, &fs); memset(&tv_sel, 0, sizeof(tv_sel)); // set to zero - imitate polling ret = select(nka->keepalive_fd + 1, &fs, NULL, NULL, &tv_sel); if (ret > 0) ret = recv(nka->keepalive_fd, buffer, sizeof(buffer), 0); #else // Check if windows signaled our event // meaning the ping reply came in // if ((hEvent != NULL) && (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0)) { if (nka->family == AF_INET6) { ret = Icmp6ParseReplies(ReplyBuffer, sizeof(ReplyBuffer)); } #ifdef V4V6_SUPPORT else if (nka->family == AF_INET) { ret = IcmpParseReplies(ReplyBuffer, sizeof(ReplyBuffer)); } #endif CloseHandle(hEvent); hEvent = NULL; } #endif //if (ret > 0) // Display(LOG_LEVEL_3, ELNotice, "internal_do_pingin", HEX_STR_ICMP_ECHO_REPLY, ret); return ret; }
static void pxping_icmp4_callback(struct pong4 *pong) { ICMP_ECHO_REPLY *reply; DWORD nreplies; size_t icmplen; struct pbuf *p; struct icmp_echo_hdr *icmph; ip_addr_t src; int mapped; nreplies = IcmpParseReplies(pong->buf, (DWORD)pong->bufsize); if (nreplies == 0) { DWORD error = GetLastError(); if (error == IP_REQ_TIMED_OUT) { DPRINTF2(("pong4: %p timed out\n", (void *)pong)); } else { DPRINTF(("pong4: %p: IcmpParseReplies: error %d\n", (void *)pong, error)); } return; } reply = (ICMP_ECHO_REPLY *)pong->buf; if (reply->Options.OptionsSize != 0) { /* don't do options */ return; } mapped = pxremap_inbound_ip4(&src, (ip_addr_t *)&reply->Address); if (mapped == PXREMAP_FAILED) { return; } if (mapped == PXREMAP_ASIS) { if (reply->Options.Ttl == 1) { return; } --reply->Options.Ttl; } if (reply->Status == IP_SUCCESS) { icmplen = sizeof(struct icmp_echo_hdr) + reply->DataSize; if ((reply->Options.Flags & IP_FLAG_DF) != 0 && IP_HLEN + icmplen > pong->netif->mtu) { return; } p = pbuf_alloc(PBUF_IP, (u16_t)icmplen, PBUF_RAM); if (RT_UNLIKELY(p == NULL)) { return; } icmph = (struct icmp_echo_hdr *)p->payload; icmph->type = ICMP_ER; icmph->code = 0; icmph->chksum = 0; icmph->id = pong->reqicmph.id; icmph->seqno = pong->reqicmph.seqno; memcpy((u8_t *)p->payload + sizeof(*icmph), reply->Data, reply->DataSize); } else { u8_t type, code; switch (reply->Status) { case IP_DEST_NET_UNREACHABLE: type = ICMP_DUR; code = ICMP_DUR_NET; break; case IP_DEST_HOST_UNREACHABLE: type = ICMP_DUR; code = ICMP_DUR_HOST; break; case IP_DEST_PROT_UNREACHABLE: type = ICMP_DUR; code = ICMP_DUR_PROTO; break; case IP_PACKET_TOO_BIG: type = ICMP_DUR; code = ICMP_DUR_FRAG; break; case IP_SOURCE_QUENCH: type = ICMP_SQ; code = 0; break; case IP_TTL_EXPIRED_TRANSIT: type = ICMP_TE; code = ICMP_TE_TTL; break; case IP_TTL_EXPIRED_REASSEM: type = ICMP_TE; code = ICMP_TE_FRAG; break; default: DPRINTF(("pong4: reply status %d, dropped\n", reply->Status)); return; } DPRINTF(("pong4: reply status %d -> type %d/code %d\n", reply->Status, type, code)); icmplen = sizeof(*icmph) + sizeof(pong->reqiph) + sizeof(pong->reqicmph); p = pbuf_alloc(PBUF_IP, (u16_t)icmplen, PBUF_RAM); if (RT_UNLIKELY(p == NULL)) { return; } icmph = (struct icmp_echo_hdr *)p->payload; icmph->type = type; icmph->code = code; icmph->chksum = 0; icmph->id = 0; icmph->seqno = 0; /* * XXX: we don't know the TTL of the request at the time this * ICMP error was generated (we can guess it was 1 for ttl * exceeded, but don't bother faking it). */ memcpy((u8_t *)p->payload + sizeof(*icmph), &pong->reqiph, sizeof(pong->reqiph)); memcpy((u8_t *)p->payload + sizeof(*icmph) + sizeof(pong->reqiph), &pong->reqicmph, sizeof(pong->reqicmph)); } icmph->chksum = inet_chksum(p->payload, (u16_t)icmplen); ip_output_if(p, &src, (ip_addr_t *)&pong->reqiph.src, /* dst */ reply->Options.Ttl, reply->Options.Tos, IPPROTO_ICMP, pong->netif); pbuf_free(p); }