Пример #1
0
int ping_recv (PING * p)
{
    socklen_t fromlen = sizeof (p->ping_from.ping_sockaddr);

    int n, rc;

    icmphdr_t *icmp;

    struct ip *ip;

    int dupflag;

    n = recvfrom (p->ping_fd,
                  (char *) p->ping_buffer, _PING_BUFLEN (p, USE_IPV6), 0,
                  (struct sockaddr *) &p->ping_from.ping_sockaddr, &fromlen);
    if (n < 0)
        return -1;

    rc = icmp_generic_decode (p->ping_buffer, n, &ip, &icmp);
    if (rc < 0)
    {
        /*FIXME: conditional */
        fprintf (stderr, "packet too short (%d bytes) from %s\n", n, inet_ntoa (p->ping_from.ping_sockaddr.sin_addr));
        return -1;
    }

    switch (icmp->icmp_type)
    {
        case ICMP_ECHOREPLY:
        case ICMP_TIMESTAMPREPLY:
        case ICMP_ADDRESSREPLY:
            /*    case ICMP_ROUTERADV: */

            if (icmp->icmp_id != p->ping_ident)
                return -1;

            if (rc)
                fprintf (stderr, "checksum mismatch from %s\n", inet_ntoa (p->ping_from.ping_sockaddr.sin_addr));

            p->ping_num_recv++;
            if (_PING_TST (p, icmp->icmp_seq))
            {
                p->ping_num_rept++;
                p->ping_num_recv--;
                dupflag = 1;
            }
            else
            {
                _PING_SET (p, icmp->icmp_seq);
                dupflag = 0;
            }

            if (p->ping_event.handler)
                (*p->ping_event.handler) (dupflag ? PEV_DUPLICATE : PEV_RESPONSE,
                                          p->ping_closure,
                                          &p->ping_dest.ping_sockaddr, &p->ping_from.ping_sockaddr, ip, icmp, n);
            break;

        case ICMP_ECHO:
        case ICMP_TIMESTAMP:
        case ICMP_ADDRESS:
            return -1;

        default:
            if (!my_echo_reply (p, icmp))
                return -1;

            if (p->ping_event.handler)
                (*p->ping_event.handler) (PEV_NOECHO,
                                          p->ping_closure,
                                          &p->ping_dest.ping_sockaddr, &p->ping_from.ping_sockaddr, ip, icmp, n);
    }
    return 0;
}
Пример #2
0
static int
ping_recv (PING * p)
{
  int dupflag, n;
  int hops = -1;
  struct msghdr msg;
  struct iovec iov;
  struct icmp6_hdr *icmp6;
  struct cmsghdr *cmsg;
  char cmsg_data[1024];

  iov.iov_base = p->ping_buffer;
  iov.iov_len = _PING_BUFLEN (p, USE_IPV6);
  msg.msg_name = &p->ping_from.ping_sockaddr6;
  msg.msg_namelen = sizeof (p->ping_from.ping_sockaddr6);
  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;
  msg.msg_control = cmsg_data;
  msg.msg_controllen = sizeof (cmsg_data);
  msg.msg_flags = 0;

  n = recvmsg (p->ping_fd, &msg, 0);
  if (n < 0)
    return -1;

  for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg))
    {
      if (cmsg->cmsg_level == IPPROTO_IPV6
	  && cmsg->cmsg_type == IPV6_HOPLIMIT)
	{
	  hops = *(int *) CMSG_DATA (cmsg);
	  break;
	}
    }

  icmp6 = (struct icmp6_hdr *) p->ping_buffer;
  if (icmp6->icmp6_type == ICMP6_ECHO_REPLY)
    {
      /* We got an echo reply.  */
      if (ntohs (icmp6->icmp6_id) != p->ping_ident)
	return -1;		/* It's not a response to us.  */

      if (_PING_TST (p, ntohs (icmp6->icmp6_seq)))
	{
	  /* We already got the reply for this echo request.  */
	  p->ping_num_rept++;
	  dupflag = 1;
	}
      else
	{
	  _PING_SET (p, ntohs (icmp6->icmp6_seq));
	  p->ping_num_recv++;
	  dupflag = 0;
	}

      print_echo (dupflag, hops, p->ping_closure, &p->ping_dest.ping_sockaddr6,
		  &p->ping_from.ping_sockaddr6, icmp6, n);

    }
  else
    {
      /* We got an error reply.  */
      if (!my_echo_reply (p, icmp6))
	return -1;		/* It's not for us.  */

      print_icmp_error (&p->ping_from.ping_sockaddr6, icmp6, n);
    }

  return 0;
}