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

📄 mtrace.c

📁 mtrace源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	    else		log(LOG_ERR, 0, "while checking for Solaris bug: Sent %d bytes and got back %d!", IGMP_MINLEN + 8, ip->ip_len);	    break;	}    }}#endif/* * Construct an IGMP message in the output packet buffer.  The caller may * have already placed data in that buffer, of length 'datalen'.  Then send * the message from the interface with IP address 'src' to destination 'dst'. */voidsend_igmp(src, dst, type, code, group, datalen)    u_int32 src, dst;    int type, code;    u_int32 group;    int datalen;{    struct sockaddr_in sdst;    struct ip *ip;    struct igmp *igmp;    int setloop = 0;    static int raset = 0;    int sendra = 0;    int sendlen;    ip                      = (struct ip *)send_buf;    ip->ip_src.s_addr       = src;    ip->ip_dst.s_addr       = dst;    ip->ip_len              = MIN_IP_HEADER_LEN + IGMP_MINLEN + datalen;    sendlen		    = ip->ip_len;#ifdef SUNOS5    ip->ip_len		   += ip_addlen;#endif#ifdef RAW_OUTPUT_IS_RAW    ip->ip_len		    = htons(ip->ip_len);#endif    igmp                    = (struct igmp *)(send_buf + MIN_IP_HEADER_LEN);    igmp->igmp_type         = type;    igmp->igmp_code         = code;    igmp->igmp_group.s_addr = group;    igmp->igmp_cksum        = 0;    igmp->igmp_cksum        = inet_cksum((u_short *)igmp,					 IGMP_MINLEN + datalen);    if (IN_MULTICAST(ntohl(dst))) {	k_set_if(src);	setloop = 1;	k_set_loop(TRUE);	if (dst != allrtrs_group)	    sendra = 1;    }    if (sendopts && sendra && !raset) {	setsockopt(igmp_socket, IPPROTO_IP, IP_OPTIONS,			router_alert, sizeof(router_alert));	raset = 1;    } else if (!sendra && raset) {#ifdef SUNOS5	/*	 * SunOS5 < 5.6 cannot properly reset the IP_OPTIONS "socket"	 * option.  Instead, set up a string of 4 EOL's.	 */	setsockopt(igmp_socket, IPPROTO_IP, IP_OPTIONS,			eol, sizeof(eol));#else	setsockopt(igmp_socket, IPPROTO_IP, IP_OPTIONS,			NULL, 0);#endif	raset = 0;    }    bzero(&sdst, sizeof(sdst));    sdst.sin_family = AF_INET;#if (defined(BSD) && (BSD >= 199103))    sdst.sin_len = sizeof(sdst);#endif    sdst.sin_addr.s_addr = dst;    if (sendto(igmp_socket, send_buf, sendlen, 0,			(struct sockaddr *)&sdst, sizeof(sdst)) < 0) {	    log(LOG_WARNING, errno, "sendto to %s on %s",		inet_fmt(dst, s1), inet_fmt(src, s2));    }    if (setloop)	    k_set_loop(FALSE);    log(LOG_DEBUG, 0, "SENT %s from %-15s to %s",	type == IGMP_MTRACE ? "mtrace request" : "ask_neighbors",	src == INADDR_ANY ? "INADDR_ANY" : inet_fmt(src, s1),	inet_fmt(dst, s2));}/* * inet_cksum extracted from: *			P I N G . C * * Author - *	Mike Muuss *	U. S. Army Ballistic Research Laboratory *	December, 1983 * Modified at Uc Berkeley * * (ping.c) Status - *	Public Domain.  Distribution Unlimited. * *			I N _ C K S U M * * Checksum routine for Internet Protocol family headers (C Version) * */intinet_cksum(addr, len)	u_short *addr;	u_int len;{	register int nleft = (int)len;	register u_short *w = addr;	u_short answer = 0;	register int sum = 0;	/*	 *  Our algorithm is simple, using a 32 bit accumulator (sum),	 *  we add sequential 16 bit words to it, and at the end, fold	 *  back all the carry bits from the top 16 bits into the lower	 *  16 bits.	 */	while (nleft > 1)  {		sum += *w++;		nleft -= 2;	}	/* mop up an odd byte, if necessary */	if (nleft == 1) {		*(u_char *) (&answer) = *(u_char *)w ;		sum += answer;	}	/*	 * add back carry outs from top 16 bits to low 16 bits	 */	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */	sum += (sum >> 16);			/* add carry */	answer = ~sum;				/* truncate to 16 bits */	return (answer);}voidk_set_rcvbuf(bufsize)    int bufsize;{    if (setsockopt(igmp_socket, SOL_SOCKET, SO_RCVBUF,		   (char *)&bufsize, sizeof(bufsize)) < 0)	log(LOG_ERR, errno, "setsockopt SO_RCVBUF %u", bufsize);}voidk_hdr_include(bool)    int bool;{#ifdef IP_HDRINCL    if (setsockopt(igmp_socket, IPPROTO_IP, IP_HDRINCL,		   (char *)&bool, sizeof(bool)) < 0)	log(LOG_ERR, errno, "setsockopt IP_HDRINCL %u", bool);#endif}voidk_set_ttl(t)    int t;{    u_char ttl;    ttl = t;    if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_TTL,		   (char *)&ttl, sizeof(ttl)) < 0)	log(LOG_ERR, errno, "setsockopt IP_MULTICAST_TTL %u", ttl);}voidk_set_loop(l)    int l;{    u_char loop;    loop = l;    if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_LOOP,		   (char *)&loop, sizeof(loop)) < 0)	log(LOG_ERR, errno, "setsockopt IP_MULTICAST_LOOP %u", loop);}voidk_set_if(ifa)    u_int32 ifa;{    struct in_addr adr;    adr.s_addr = ifa;    if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_IF,		   (char *)&adr, sizeof(adr)) < 0)	log(LOG_ERR, errno, "setsockopt IP_MULTICAST_IF %s",	    		    inet_fmt(ifa, s1));}voidk_join(grp, ifa)    u_int32 grp;    u_int32 ifa;{    struct ip_mreq mreq;    mreq.imr_multiaddr.s_addr = grp;    mreq.imr_interface.s_addr = ifa;    if (setsockopt(igmp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,		   (char *)&mreq, sizeof(mreq)) < 0)	log(LOG_WARNING, errno, "can't join group %s on interface %s",				inet_fmt(grp, s1), inet_fmt(ifa, s2));}voidk_leave(grp, ifa)    u_int32 grp;    u_int32 ifa;{    struct ip_mreq mreq;    mreq.imr_multiaddr.s_addr = grp;    mreq.imr_interface.s_addr = ifa;    if (setsockopt(igmp_socket, IPPROTO_IP, IP_DROP_MEMBERSHIP,		   (char *)&mreq, sizeof(mreq)) < 0)	log(LOG_WARNING, errno, "can't leave group %s on interface %s",				inet_fmt(grp, s1), inet_fmt(ifa, s2));}/* * Convert an IP address in u_long (network) format into a printable string. */char *inet_fmt(addr, s)    u_int32 addr;    char *s;{    register u_char *a;    a = (u_char *)&addr;    sprintf(s, "%u.%u.%u.%u", a[0], a[1], a[2], a[3]);    return (s);}/* * Convert an IP subnet number in u_long (network) format into a printable * string including the netmask as a number of bits. */char *inet_fmts(addr, mask, s)    u_int32 addr, mask;    char *s;{    register u_char *a, *m;    int bits;    if ((addr == 0) && (mask == 0)) {	sprintf(s, "default");	return (s);    }    a = (u_char *)&addr;    m = (u_char *)&mask;    bits = 33 - ffs(ntohl(mask));    if      (m[3] != 0) sprintf(s, "%u.%u.%u.%u/%d", a[0], a[1], a[2], a[3],						bits);    else if (m[2] != 0) sprintf(s, "%u.%u.%u/%d",    a[0], a[1], a[2], bits);    else if (m[1] != 0) sprintf(s, "%u.%u/%d",       a[0], a[1], bits);    else                sprintf(s, "%u/%d",          a[0], bits);    return (s);}char   *inet_name(addr)    u_int32  addr;{    struct hostent *e;    e = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);    return e ? e->h_name : "?";}u_int32 host_addr(name)    char   *name;{    struct hostent *e = (struct hostent *)0;    u_int32  addr;    int	i, dots = 3;    char	buf[40];    char	*ip = name;    char	*op = buf;    /*     * Undo BSD's favor -- take fewer than 4 octets as net/subnet address     * if the name is all numeric.     */    for (i = sizeof(buf) - 7; i > 0; --i) {	if (*ip == '.') --dots;	else if (*ip == '\0') break;	else if (!isdigit(*ip)) dots = 0;  /* Not numeric, don't add zeroes */	*op++ = *ip++;    }    for (i = 0; i < dots; ++i) {	*op++ = '.';	*op++ = '0';    }    *op = '\0';    if (dots <= 0)	e = gethostbyname(name);    if (e && (e->h_length == sizeof(addr))) {	memcpy((char *)&addr, e->h_addr_list[0], e->h_length);	if (e->h_addr_list[1])	    fprintf(stderr, "Warning: %s has multiple addresses, using %s\n",			name, inet_fmt(addr, s1));    } else {	addr = inet_addr(buf);	if (addr == -1 || (IN_MULTICAST(addr) && dots)) {	    addr = 0;	    printf("Could not parse %s as host name or address\n", name);	}    }    return addr;}char *proto_type(type)    u_int type;{    static char buf[80];    switch (type) {      case PROTO_DVMRP:	return ("DVMRP");      case PROTO_MOSPF:	return ("MOSPF");      case PROTO_PIM:	return ("PIM");      case PROTO_CBT:	return ("CBT");      case PROTO_PIM_SPECIAL:	return ("PIM/Special");      case PROTO_PIM_STATIC:	return ("PIM/Static");      case PROTO_DVMRP_STATIC:	return ("DVMRP/Static");      case PROTO_PIM_BGP4PLUS:	return ("PIM/BGP4+");      case PROTO_CBT_SPECIAL:	return ("CBT/Special");      case PROTO_CBT_STATIC:	return ("CBT/Static");      case PROTO_PIM_ASSERT:	return ("PIM/Assert");      case 0:	return ("None");      default:	(void) sprintf(buf, "Unknown protocol code %d", type);	return (buf);    }}char *flag_type(type)    u_int type;{    static char buf[80];    switch (type) {      case TR_NO_ERR:	return ("");      case TR_WRONG_IF:	return ("Wrong interface");      case TR_PRUNED:	return ("Prune sent upstream");      case TR_OPRUNED:	return ("Output pruned");      case TR_SCOPED:	return ("Hit scope boundary");      case TR_NO_RTE:	return ("No route");      case TR_NO_FWD:	return ("Not forwarding");      case TR_HIT_RP:	return ("Reached RP/Core");      case TR_RPF_IF:	return ("RPF Interface");      case TR_NO_MULTI:	return ("Multicast disabled");      case TR_OLD_ROUTER:	return ("Next router no mtrace");      case TR_NO_SPACE:	return ("No space in packet");      case TR_ADMIN_PROHIB:	return ("Admin. Prohibited");      default:	(void) sprintf(buf, "Unknown error code %d", type);	return (buf);    }}    /* * If destination is on a local net, get the netmask, else set the * netmask to all ones.  There are two side effects: if the local * address was not explicitly set, and if the destination is on a * local net, use that one; in either case, verify that the local * address is valid. */u_int32get_netmask(s, dst)    int s;    u_int32 *dst;{    unsigned int n;    struct ifconf ifc;    struct ifreq *ifrp, *ifend;    u_int32 if_addr, if_mask;    u_int32 retval = 0xFFFFFFFF;    int found = FALSE;    int num_ifreq = 32;    ifc.ifc_len = num_ifreq * sizeof(struct ifreq);    ifc.ifc_buf = malloc(ifc.ifc_len);    while (ifc.ifc_buf) {	if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {	    perror("ioctl SIOCGIFCONF");	    return retval;	}	/*	 * If the buffer was large enough to hold all the addresses	 * then break out, otherwise increase the buffer size and	 * try again.	 *	 * The only way to know that we definitely had enough space	 * is to know that there was enough space for at least one	 * more struct ifreq. ???	 */	if ((num_ifreq * sizeof(struct ifreq)) >=	     ifc.ifc_len + sizeof(struct ifreq))	     break;	num_ifreq *= 2;	ifc.ifc_len = num_ifreq * sizeof(struct ifreq);	ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);    }    if (ifc.ifc_buf == NULL) {	fprintf(stderr, "getting interface list: ran out of memory");	exit(1);    }

⌨️ 快捷键说明

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