⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mtrace.c

📁 mtrace源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (r->tr_outaddr == 0)		    r->tr_outaddr = recvaddr.sin_addr.s_addr;		/*		 * A match, we'll keep this one.		 */		if (len > code) {		    fprintf(stderr,			    "Num hops received (%d) exceeds request (%d)\n",			    len, code);		}		rquery->tr_raddr = query->tr_raddr;	/* Insure these are */		TR_SETTTL(rquery->tr_rttlqid, TR_GETTTL(query->tr_rttlqid));							/* as we sent them */		break;	      default:		continue;	    }	    /*	     * We're pretty sure we want to use this packet now,	     * but if the caller gave a callback function, it might	     * want to handle it instead.  Give the callback a chance,	     * unless the select timed out (in which case the only way	     * to get here is because the callback returned a packet).	     */	    if (callback && (count != 0) && ((callback)(0, recv_buf, recvlen, igmp, igmpdatalen, (struct sockaddr*)&recvaddr, &socklen, &tr)) == 0) {		/*		 * The callback function didn't like this packet.		 * Go try receiving another one.		 */		continue;	    }	    /*	     * Most of the sanity checking done at this point.	     * Return this packet we have been waiting for.	     */	    if (save) {		save->qtime = ((tq.tv_sec + JAN_1970) << 16) +			      (tq.tv_usec << 10) / 15625;		save->rtime = ((tr.tv_sec + JAN_1970) << 16) +			      (tr.tv_usec << 10) / 15625;		save->len = len;		bcopy((char *)igmp, (char *)&save->igmp, ipdatalen);	    }	    return (recvlen);	}    }    return (0);}/* * Most of this code is duplicated elsewhere.  I'm not sure if * the duplication is absolutely required or not. * * Ideally, this would keep track of ongoing statistics * collection and print out statistics.  (& keep track * of h-b-h traces and only print the longest)  For now, * it just snoops on what traces it can. */voidpassive_mode(){    struct timeval tr;    struct ip *ip;    struct igmp *igmp;    struct tr_resp *r;    struct sockaddr_in recvaddr;    struct tm *now;    char timebuf[32];    int socklen;    int ipdatalen, iphdrlen, igmpdatalen;    int len, recvlen;    int qid;    u_int32 smask;    struct mtrace *remembered = NULL, *m, *n, **nn;    int pc = 0;    if (raddr) {	if (IN_MULTICAST(ntohl(raddr))) k_join(raddr, lcl_addr);    } else k_join(htonl(0xE0000120), lcl_addr);    while (1) {	fflush(stdout);		/* make sure previous trace is flushed */	socklen = sizeof(recvaddr);	recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,			   0, (struct sockaddr *)&recvaddr, &socklen);	gettimeofday(&tr,0);	if (recvlen <= 0) {	    if (recvlen && errno != EINTR) perror("recvfrom");	    continue;	}	if (recvlen < sizeof(struct ip)) {	    fprintf(stderr,		    "packet too short (%u bytes) for IP header", recvlen);	    continue;	}	ip = (struct ip *) recv_buf;	if (ip->ip_p == 0)	/* ignore cache creation requests */	    continue;	iphdrlen = ip->ip_hl << 2;#ifdef RAW_INPUT_IS_RAW	ipdatalen = ntohs(ip->ip_len);#else	ipdatalen = ip->ip_len;#endif	if (iphdrlen + ipdatalen != recvlen) {	    fprintf(stderr,		    "packet shorter (%u bytes) than hdr+data len (%u+%u)\n",		    recvlen, iphdrlen, ipdatalen);	    continue;	}	igmp = (struct igmp *) (recv_buf + iphdrlen);	igmpdatalen = ipdatalen - IGMP_MINLEN;	if (igmpdatalen < 0) {	    fprintf(stderr,		    "IP data field too short (%u bytes) for IGMP from %s\n",		    ipdatalen, inet_fmt(ip->ip_src.s_addr, s1));	    continue;	}	switch (igmp->igmp_type) {	  case IGMP_MTRACE:	    /* For backward compatibility with 3.3 */	  case IGMP_MTRACE_RESP:	    if (igmpdatalen < QLEN) continue;	    if ((igmpdatalen - QLEN)%RLEN) {		printf("packet with incorrect datalen\n");		continue;	    }	    len = (igmpdatalen - QLEN)/RLEN;	    break;	  default:	    continue;	}	base.qtime = ((tr.tv_sec + JAN_1970) << 16) +		      (tr.tv_usec << 10) / 15625;	base.rtime = ((tr.tv_sec + JAN_1970) << 16) +		      (tr.tv_usec << 10) / 15625;	base.len = len;	bcopy((char *)igmp, (char *)&base.igmp, ipdatalen);	/*	 * If the user specified which traces to monitor,	 * only accept traces that correspond to the	 * request	 */	if ((qsrc != 0 && qsrc != base.qhdr.tr_src) ||	    (qdst != 0 && qdst != base.qhdr.tr_dst) ||	    (qgrp != 0 && qgrp != igmp->igmp_group.s_addr))	    continue;	/* XXX This should be a hash table */	/* XXX garbage-collection should be more efficient */	for (nn = &remembered, n = *nn, m = 0; n; n = *nn) {	    if ((n->base.qhdr.tr_src == base.qhdr.tr_src) &&		(n->base.qhdr.tr_dst == base.qhdr.tr_dst) &&		(n->base.igmp.igmp_group.s_addr == igmp->igmp_group.s_addr)) {		m = n;		m->last = tr;	    }	    if (tr.tv_sec - n->last.tv_sec > 500) { /* XXX don't hardcode */		*nn = n->next;		free(n);	    } else {		nn = &n->next;	    }	}	now = localtime(&tr.tv_sec);	strftime(timebuf, sizeof(timebuf) - 1, "%b %e %k:%M:%S", now);	printf("Mtrace %s at %s",		len == 0 ? "query" :			   igmp->igmp_type == IGMP_MTRACE_RESP ? "response" :								 "in transit",		timebuf);	if (len == 0)		printf(" by %s", inet_fmt(recvaddr.sin_addr.s_addr, s1));	if (!IN_MULTICAST(base.qhdr.tr_raddr))		printf(", resp to %s", (len == 0 && recvaddr.sin_addr.s_addr == base.qhdr.tr_raddr) ? "same" : inet_fmt(base.qhdr.tr_raddr, s1));	else		printf(", respttl %d", TR_GETTTL(base.qhdr.tr_rttlqid));	printf(", qid %06x\n", qid = TR_GETQID(base.qhdr.tr_rttlqid));	printf("packet from %s to %s\n",		inet_fmt(ip->ip_src.s_addr, s1),		inet_fmt(ip->ip_dst.s_addr, s2));	printf("from %s to %s via group %s (mxhop=%d)\n",		inet_fmt(base.qhdr.tr_dst, s1), inet_fmt(base.qhdr.tr_src, s2),		inet_fmt(igmp->igmp_group.s_addr, s3), igmp->igmp_code);	if (len == 0) {	    printf("\n");	    continue;	}	r = base.resps + base.len - 1;	/*	 * Some routers will return error messages without	 * filling in their addresses.  We fill in the address	 * for them.	 */	if (r->tr_outaddr == 0)	    r->tr_outaddr = recvaddr.sin_addr.s_addr;	/*	 * If there was a previous trace, it see if this is a	 * statistics candidate.	 */	if (m && base.len == m->base.len &&		!(pc = path_changed(&m->base, &base))) {	    /*	     * Some mtrace responders send multiple copies of the same	     * reply.  Skip this packet if it's got the same query-id	     * as the last one.	     */	    if (m->lastqid == qid) {		printf("Skipping duplicate reply\n");		continue;	    }	    m->lastqid = qid;	    ++m->nresp;	    bcopy(&base, m->new, sizeof(base));	    printf("Results after %d seconds:\n\n",		   (int)((m->new->qtime - m->base.qtime) >> 16));	    fixup_stats(&m->base, m->prev, m->new, m->bugs);	    print_stats(&m->base, m->prev, m->new, m->bugs, m->names);	    m->prev = m->new;	    m->new = &m->incr[(m->nresp & 1)];	    continue;	}	if (m == NULL) {	    m = (struct mtrace *)malloc(sizeof(struct mtrace));	    if (m == NULL) {		fprintf(stderr, "Out of memory!\n");		continue;	    }	    bzero(m, sizeof(struct mtrace));	    m->next = remembered;	    remembered = m;	    bcopy(&tr, &m->last, sizeof(tr));	}	/* Either it's a hop-by-hop in progress, or the path changed. */	if (pc) {	    printf("[Path Changed...]\n");	    bzero(m->bugs, sizeof(m->bugs));	}	bcopy(&base, &m->base, sizeof(base));	m->prev = &m->base;	m->new = &m->incr[0];	m->nresp = 0;	printf("  0  ");	print_host(base.qhdr.tr_dst);	printf("\n");	print_trace(1, &base, m->names);	VAL_TO_MASK(smask, r->tr_smask);	if ((r->tr_inaddr & smask) == (base.qhdr.tr_src & smask)) {	    printf("%3d  ", -(base.len+1));	    print_host(base.qhdr.tr_src);	    printf("\n");	} else if (r->tr_rmtaddr != 0) {	    printf("%3d  ", -(base.len+1));	    print_host(r->tr_rmtaddr);	    printf(" %s\n", r->tr_rflags == TR_OLD_ROUTER ?				   "doesn't support mtrace"				 : "is the next hop");	}	printf("\n");    }}char *print_host(addr)    u_int32 addr;{    return print_host2(addr, 0);}/* * On some routers, one interface has a name and the other doesn't. * We always print the address of the outgoing interface, but can * sometimes get the name from the incoming interface.  This might be * confusing but should be slightly more helpful than just a "?". */char *print_host2(addr1, addr2)    u_int32 addr1, addr2;{    char *name;    if (numeric) {	printf("%s", inet_fmt(addr1, s1));	return ("");    }    name = inet_name(addr1);    if (*name == '?' && *(name + 1) == '\0' && addr2 != 0)	name = inet_name(addr2);    printf("%s (%s)", name, inet_fmt(addr1, s1));    return (name);}/* * Print responses as received (reverse path from dst to src) */voidprint_trace(idx, buf, names)    int idx;    struct resp_buf *buf;    char **names;{    struct tr_resp *r;    char *name;    int i;    int hop;    char *ms;    i = abs(idx);    r = buf->resps + i - 1;    for (; i <= buf->len; ++i, ++r) {	if (idx > 0) printf("%3d  ", -i);	name = print_host2(r->tr_outaddr, r->tr_inaddr);	if (r->tr_rflags != TR_NO_RTE)	    printf("  %s  thresh^ %d", proto_type(r->tr_rproto), r->tr_fttl);	if (verbose) {	    hop = t_diff(ntohl(r->tr_qarr), buf->qtime);	    ms = scale(&hop);	    printf("  %d%s", hop, ms);	}	printf("  %s", flag_type(r->tr_rflags));	if (i > 1 && r->tr_outaddr != (r-1)->tr_rmtaddr) {	    printf(" !RPF!");	    print_host((r-1)->tr_rmtaddr);	}	if (r->tr_rflags != TR_NO_RTE) {	    if (r->tr_smask <= 1)    /* MASK_TO_VAL() returns 1 for default */		printf(" [default]");	    else if (verbose) {		u_int32 smask;		VAL_TO_MASK(smask, r->tr_smask);		printf(" [%s]", inet_fmts(buf->qhdr.tr_src & smask,							smask, s1));	    }	}	printf("\n");	if (names[i-1])	    free(names[i-1]);	names[i-1]=malloc(strlen(name) + 1);	strcpy(names[i-1], name);    }}/* * See what kind of router is the next hop */intwhat_kind(buf, why)    struct resp_buf *buf;    char *why;{    u_int32 smask;    int retval;    int hops = buf->len;    struct tr_resp *r = buf->resps + hops - 1;    u_int32 next = r->tr_rmtaddr;    retval = send_recv(next, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS2, 1, &incr[0], NULL);    print_host(next);    if (retval) {	u_int32 version = ntohl(incr[0].igmp.igmp_group.s_addr);	u_int32 *p = (u_int32 *)incr[0].ndata;	u_int32 *ep = p + (incr[0].len >> 2);	char *type = "version ";	retval = 0;	switch (version & 0xFF) {	  case 1:	    type = "proteon/mrouted ";	    retval = 1;	    break;	  case 10:	  case 11:	    type = "cisco ";	}	printf(" [%s%d.%d] %s\n",	       type, version & 0xFF, (version >> 8) & 0xFF,	       why);	VAL_TO_MASK(smask, r->tr_smask);	while (p < ep) {	    u_int32 laddr = *p++;	    int flags = (ntohl(*p) & 0xFF00) >> 8;	    int n = ntohl(*p++) & 0xFF;	    if (!(flags & (DVMRP_NF_DOWN | DVMRP_NF_DISABLED)) &&		 (laddr & smask) == (qsrc & smask)) {		printf("%3d  ", -(hops+2));		print_host(qsrc);		printf("\n");		return 1;	    }	    p += n;	}	return retval;    }    printf(" %s\n", why);    return 0;}char *scale(hop)    int *hop;{    if (*hop > -1000 && *hop < 10000) return (" ms");    *hop /= 1000;    if (*hop > -1000 && *hop < 10000) return (" s ");    return ("s ");}/* * Calculate and print one line of packet loss and packet rate statistics. * Checks for count of all ones from mrouted 2.3 that doesn't have counters. */#define NEITHER 0#define INS     1#define OUTS    2#define BOTH    3voidstat_line(r, s, have_next, rst)    struct tr_resp *r, *s;    int have_next;    int *rst;{    int timediff = (ntohl(s->tr_qarr) - ntohl(r->tr_qarr)) >> 16;    int v_lost, v_pct;    int g_lost, g_pct;    int v_out = ntohl(s->tr_vifout) - ntohl(r->tr_vifout);    int g_out = ntohl(s->tr_pktcnt) - ntohl(r->tr_pktcnt);    int v_pps, g_pps;    char v_str[8], g_str[8];    int vhave = NEITHER;    int ghave = NEITHER;    int gmissing = NEITHER;    char whochar;    int badtime = 0;    if (timediff == 0) {	badtime = 1;	/* Might be 32 bits of int seconds instead of 16int+16frac */	timediff = ntohl(s->tr_qarr) - ntohl(r->tr_qarr);	if (timediff == 0 || abs(timediff - statint) > statint)	    timediff = 1;    }    v_pps = v_out / timediff;    g_pps = g_out / timediff;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -