Пример #1
0
/**
 * return 0 on success/got reply,
 *        <0 on fail. Errno returned.
 *        >0 on success, but no packet (EINTR or dup packet)
 */
static int
recvEchoReply(int fd)
{
	int err;
        char packet[1024];
        ssize_t packetlen;
	double now;
	char lag[128];
        int isDup = 0;
        int isReorder = 0;
        int ttl;
        int tos;
        char tosString[128] = {0};
        char ttlString[128] = {0};
        struct GtpReply gtp;

	if (options.verbose > 2) {
		fprintf(stderr, "%s: recvEchoReply()\n", argv0);
	}

	now = clock_get_dbl();
	
	memset(packet, 0, sizeof(packet));
        if (0 > (packetlen = doRecv(fd,
                                    (void*)packet,
                                    sizeof(packet),
                                    &ttl,
                                    &tos))) {
		switch(errno) {
                case ECONNREFUSED:
                        connectionRefused++;
			handleRecvErr(fd, "Port closed", 0);
                        return 1;
		case EINTR:
                        return 1;
                case EHOSTUNREACH:
			handleRecvErr(fd, "Host unreachable or TTL exceeded",
                                      0);
                        return 1;
		default:
			err = errno;
			fprintf(stderr, "%s: recv(%d, ...): %s\n",
				argv0, fd, strerror(errno));
                        return err;
		}
	}

        /* create ttl string */
        if (0 <= ttl) {
                snprintf(ttlString, sizeof(ttlString), "ttl=%d ", ttl);
        }

        /* create tos string */
        if (0 <= tos) {
                char scratch[128];
                snprintf(tosString, sizeof(tosString),
                         "%s ", tos2String(tos,
                                           scratch,
                                           sizeof(scratch)));
        }

        gtp = parseReply(packet, packetlen);
        if (!gtp.ok) {
                return 1;
        }

	if (gtp.msg != GTPMSG_ECHOREPLY) {
		fprintf(stderr,
			"%s: Got non-EchoReply type of msg (type: %d)\n",
			argv0, gtp.msg);
                return 1;
	}

        if (curSeq - gtp.seq >= TRACKPINGS_SIZE) {
		strcpy(lag, "Inf");
	} else {
                int pos = gtp.seq % TRACKPINGS_SIZE;
                double lagf = now - sendTimes[pos];
                if (gotIt[pos]) {
                        isDup = 1;
                }
                gotIt[pos]++;
		snprintf(lag, sizeof(lag), "%.2f ms", 1000 * lagf);
                if (!isDup) {
                        totalTime += lagf;
                        totalTimeSquared += lagf * lagf;
                        totalTimeCount++;
                        if ((0 > totalMin) || (lagf < totalMin)) {
                                totalMin = lagf;
                        }
                        if ((0 > totalMax) || (lagf > totalMax)) {
                                totalMax = lagf;
                        }
                }
                if (options.autowait) {
                        options.wait = 2 * (totalTime / totalTimeCount);
                        if (options.verbose > 1) {
                                fprintf(stderr,
                                        "%s: Adjusting waittime to %.6f\n",
                                        argv0, options.wait);
                        }
                }
	}

        /* detect packet reordering */
        if (!isDup) {
                if (highestSeq > gtp.seq) {
                        reorder++;
                        isReorder = 1;
                } else {
                        highestSeq = gtp.seq;
                }
        }

        if (options.flood) {
                if (!isDup) {
                        printf("\b \b");
                }
        } else {
                printf("%u bytes from %s: ver=%d seq=%u %s%stime=%s%s%s\n",
                       (int)packetlen,
                       options.targetip,
                       gtp.version,
                       gtp.seq,
                       tosString[0] ? tosString : "",
                       ttlString[0] ? ttlString : "",
                       lag,
                       isDup ? " (DUP)" : "",
                       isReorder ? " (out of order)" : "");
        }
        if (isDup) {
                dups++;
        }
	return isDup;
}
Пример #2
0
/**
 * return:
 *      0 if no error
 *      1 if TTL exceeded
 *     >1 if other icmp-like error
 */
int
handleRecvErr(int fd, const char *reason, double lastPingTime)
{
	struct msghdr msg;
	struct cmsghdr *cmsg;
	char cbuf[512];
	char buf[5120];
	struct sockaddr_storage sa;
	struct iovec iov;
	int n;
	int returnttl = -1;
        char *tos = 0;
        int ret = 0;

        /* ignore reason, we know better */
        reason = reason;

	/* get error data */
	iov.iov_base = buf;
	iov.iov_len = sizeof(buf);
	memset(&msg, 0, sizeof(msg));
	msg.msg_name = (char*)&sa;
	msg.msg_namelen = sizeof(sa);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = cbuf;
	msg.msg_controllen = sizeof(cbuf);
	
	if (0 > (n = recvmsg(fd, &msg, MSG_ERRQUEUE))) {
		if (errno == EAGAIN) {
                        goto errout;
		}
		fprintf(stderr, "%s: recvmsg(%d, ..., MSG_ERRQUEUE): %s\n",
			argv0, fd, strerror(errno));
                goto errout;
	}

	/* First find ttl */
	for (cmsg = CMSG_FIRSTHDR(&msg);
	     cmsg;
	     cmsg = CMSG_NXTHDR(&msg, cmsg)) {
		if ((cmsg->cmsg_level == SOL_IP
		     || cmsg->cmsg_level == SOL_IPV6)
		    && (cmsg->cmsg_type == IP_TTL
			|| cmsg->cmsg_type == IPV6_HOPLIMIT
			|| cmsg->cmsg_type == REAL_IPV6_HOPLIMIT
			)) {
			returnttl = *(int*)CMSG_DATA(cmsg);
		}
	}
	for (cmsg = CMSG_FIRSTHDR(&msg);
	     cmsg;
	     cmsg = CMSG_NXTHDR(&msg, cmsg)) {
                if (cmsg->cmsg_level == SOL_IP
		    || cmsg->cmsg_level == SOL_IPV6) {
			switch(cmsg->cmsg_type) {
                        case IP_TOS:
#ifdef IPV6_TCLASS
                        case IPV6_TCLASS:
#endif
                                {
                                        char scratch[128];
                                        free(tos);
                                        if (!(tos = malloc(128))) {
                                                fprintf(stderr,
                                                        "%s: "
                                                        "malloc(128): %s\n",
                                                        argv0,
                                                        strerror(errno));
                                                goto errout;
                                        }
                                        snprintf(tos, 128,
                                                 "%s",
                                                 tos2String(*(unsigned char*)
                                                            CMSG_DATA(cmsg),
                                                            scratch,
                                                            sizeof(scratch)));
                                        break;
                                }
			case IP_RECVERR:
			case IPV6_RECVERR:
                                ret = handleRecvErrSEE((struct
                                                        sock_extended_err*)
                                                       CMSG_DATA(cmsg),
                                                       returnttl,
                                                       tos,
                                                       lastPingTime);
				break;
			case IP_TTL:
#if IPV6_HOPLIMIT != REAL_IPV6_HOPLIMIT
			case REAL_IPV6_HOPLIMIT:
#endif
			case IPV6_HOPLIMIT:
				/* ignore */
				break;
			default:
				fprintf(stderr,
					"%s: Got cmsg type: %d",
					argv0,
					cmsg->cmsg_type);
				if (0 < returnttl) {
					fprintf(stderr, ". Return TTL: %d",
						returnttl);
				}
				printf("\n");
			}

		}
	}
 errout:;
        free(tos);
        return ret;
}