Пример #1
0
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;
}
Пример #2
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;
}
Пример #3
0
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);
}