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; }
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; }