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

📄 icmp6.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	np->ttl = HOP_LIMIT;	np->vcf[0] = 0x06 << 4;	ipriv->out[UnreachableV6]++;	if(free)		ipiput6(f, ifc, nbp);	else {		ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);		return;	}clean:	runlock(ifc);	freeblist(bp);}extern voidicmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp){	Block *nbp;	IPICMP *np;	Ip6hdr	*p;	int osz = BLEN(bp);	int sz = MIN(sizeof(IPICMP) + osz, v6MINTU);	Proto	*icmp = f->t2p[ICMPv6];	Icmppriv6 *ipriv = icmp->priv;	p = (Ip6hdr *) bp->rp;	if(isv6mcast(p->src)) 		return;	nbp = newIPICMP(sz);	np = (IPICMP *) nbp->rp;	if(ipv6anylocal(ifc, np->src)) {		netlog(f, Logicmp, "send icmpttlexceeded6 -> s%I d%I\n", p->src, p->dst);	}	else {		netlog(f, Logicmp, "icmpttlexceeded6 fail -> s%I d%I\n", p->src, p->dst);		return;	}	memmove(np->dst, p->src, IPaddrlen);	np->type = TimeExceedV6;	np->code = 0;	memmove(nbp->rp + sizeof(IPICMP), bp->rp, sz - sizeof(IPICMP));	set_cksum(nbp);	np->ttl = HOP_LIMIT;	np->vcf[0] = 0x06 << 4;	ipriv->out[TimeExceedV6]++;	ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);}extern voidicmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp){	Block *nbp;	IPICMP *np;	Ip6hdr	*p;	int osz = BLEN(bp);	int sz = MIN(sizeof(IPICMP) + osz, v6MINTU);	Proto	*icmp = f->t2p[ICMPv6];	Icmppriv6 *ipriv = icmp->priv;	p = (Ip6hdr *) bp->rp;	if(isv6mcast(p->src)) 		return;	nbp = newIPICMP(sz);	np = (IPICMP *) nbp->rp;	if(ipv6anylocal(ifc, np->src)) {		netlog(f, Logicmp, "send icmppkttoobig6 -> s%I d%I\n", p->src, p->dst);	}	else {		netlog(f, Logicmp, "icmppkttoobig6 fail -> s%I d%I\n", p->src, p->dst);		return;	}	memmove(np->dst, p->src, IPaddrlen);	np->type = PacketTooBigV6;	np->code = 0;	hnputl(np->icmpid, ifc->maxtu - ifc->m->hsize);	memmove(nbp->rp + sizeof(IPICMP), bp->rp, sz - sizeof(IPICMP));	set_cksum(nbp);	np->ttl = HOP_LIMIT;	np->vcf[0] = 0x06 << 4;	ipriv->out[PacketTooBigV6]++;	ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);}/* * RFC 2461, pages 39-40, pages 57-58. */static intvalid(Proto *icmp, Ipifc *ifc, Block *bp, Icmppriv6 *ipriv) {	int 	sz, osz, unsp, n, ttl, iplen;	int 	pktsz = BLEN(bp);	uchar	*packet = bp->rp;	IPICMP	*p = (IPICMP *) packet;	Ndpkt	*np;	USED(ifc);	n = blocklen(bp);	if(n < sizeof(IPICMP)) {		ipriv->stats[HlenErrs6]++;		netlog(icmp->f, Logicmp, "icmp hlen %d\n", n);		goto err;	}	iplen = nhgets(p->ploadlen);	if(iplen > n-IPV6HDR_LEN || (iplen % 1)) {		ipriv->stats[LenErrs6]++;		netlog(icmp->f, Logicmp, "icmp length %d\n", iplen);		goto err;	}	// Rather than construct explicit pseudoheader, overwrite IPv6 header	if(p->proto != ICMPv6) {		// This code assumes no extension headers!!!		netlog(icmp->f, Logicmp, "icmp error: extension header\n");		goto err;	}	memset(packet, 0, 4);	ttl = p->ttl;	p->ttl = p->proto;	p->proto = 0;	if(ptclcsum(bp, 0, iplen + IPV6HDR_LEN)) {		ipriv->stats[CsumErrs6]++;		netlog(icmp->f, Logicmp, "icmp checksum error\n");		goto err;	}	p->proto = p->ttl;	p->ttl = ttl;	/* additional tests for some pkt types */	if( (p->type == NbrSolicit) ||		(p->type == NbrAdvert) ||		(p->type == RouterAdvert) ||		(p->type == RouterSolicit) ||		(p->type == RedirectV6) ) {		if(p->ttl != HOP_LIMIT) {			ipriv->stats[HoplimErrs6]++; 			goto err; 		}		if(p->code != 0) {			ipriv->stats[IcmpCodeErrs6]++; 			goto err; 		}		switch (p->type) {		case NbrSolicit:		case NbrAdvert:			np = (Ndpkt*) p;			if(isv6mcast(np->target)) {				ipriv->stats[TargetErrs6]++; 				goto err; 			}			if(optexsts(np) && (np->olen == 0)) {				ipriv->stats[OptlenErrs6]++; 				goto err; 			}					if(p->type == NbrSolicit) {				if(ipcmp(np->src, v6Unspecified) == 0) { 					if(!issmcast(np->dst) || optexsts(np))  {						ipriv->stats[AddrmxpErrs6]++; 						goto err;					}				}			}					if(p->type == NbrAdvert) {				if((isv6mcast(np->dst))&&(nhgets(np->icmpid) & Sflag)){					ipriv->stats[AddrmxpErrs6]++; 					goto err; 				}			}			break;			case RouterAdvert:			if(pktsz - sizeof(Ip6hdr) < 16) {				ipriv->stats[HlenErrs6]++; 				goto err; 			}			if(!islinklocal(p->src)) {				ipriv->stats[RouterAddrErrs6]++; 				goto err; 			}			sz = sizeof(IPICMP) + 8;			while ((sz+1) < pktsz) {				osz = *(packet+sz+1);				if(osz <= 0) {					ipriv->stats[OptlenErrs6]++; 					goto err; 				}					sz += 8*osz;			}			break;			case RouterSolicit:			if(pktsz - sizeof(Ip6hdr) < 8) {				ipriv->stats[HlenErrs6]++; 				goto err; 			}			unsp = (ipcmp(p->src, v6Unspecified) == 0);			sz = sizeof(IPICMP) + 8;			while ((sz+1) < pktsz) {				osz = *(packet+sz+1);				if((osz <= 0) ||					(unsp && (*(packet+sz) == slladd)) ) {					ipriv->stats[OptlenErrs6]++; 					goto err; 				}				sz += 8*osz;			}			break;			case RedirectV6:			//to be filled in			break;			default:			goto err;		}	}	return 1;err:	ipriv->stats[InErrors6]++; 	return 0;}static inttargettype(Fs *f, Ipifc *ifc, uchar *target){	Iplifc *lifc;	int t;	rlock(ifc);	if(ipproxyifc(f, ifc, target)) {		runlock(ifc);		return t_uniproxy;	}	for(lifc = ifc->lifc; lifc; lifc = lifc->next) {		if(ipcmp(lifc->local, target) == 0) {			t = (lifc->tentative) ? t_unitent : t_unirany; 			runlock(ifc);			return t;		}	}	runlock(ifc);	return 0;}static voidicmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp){	uchar	*packet = bp->rp;	IPICMP	*p = (IPICMP *)packet;	Icmppriv6 *ipriv = icmp->priv;	Block	*r;	Proto	*pr;	char	*msg, m2[128];	Ndpkt* np;	uchar pktflags;	uchar lsrc[IPaddrlen];	int refresh = 1;	Iplifc *lifc;	if(!valid(icmp, ipifc, bp, ipriv)) 		goto raise;	if(p->type <= Maxtype6)		ipriv->in[p->type]++;	else		goto raise;	switch(p->type) {	case EchoRequestV6:		r = mkechoreply6(bp);		ipriv->out[EchoReply]++;		ipoput6(icmp->f, r, 0, MAXTTL, DFLTTOS, nil);		break;	case UnreachableV6:		if(p->code > 4)			msg = unreachcode[icmp6_unkn_code];		else			msg = unreachcode[p->code];		bp->rp += sizeof(IPICMP);		if(blocklen(bp) < 8){			ipriv->stats[LenErrs6]++;			goto raise;		}		p = (IPICMP *)bp->rp;		pr = Fsrcvpcolx(icmp->f, p->proto);		if(pr != nil && pr->advise != nil) {			(*pr->advise)(pr, bp, msg);			return;		}		bp->rp -= sizeof(IPICMP);		goticmpkt6(icmp, bp, 0);		break;	case TimeExceedV6:		if(p->code == 0){			sprint(m2, "ttl exceeded at %I", p->src);			bp->rp += sizeof(IPICMP);			if(blocklen(bp) < 8){				ipriv->stats[LenErrs6]++;				goto raise;			}			p = (IPICMP *)bp->rp;			pr = Fsrcvpcolx(icmp->f, p->proto);			if(pr != nil && pr->advise != nil) {				(*pr->advise)(pr, bp, m2);				return;			}			bp->rp -= sizeof(IPICMP);		}		goticmpkt6(icmp, bp, 0);		break;	case RouterAdvert:	case RouterSolicit:		/* using lsrc as a temp, munge hdr for goticmp6 		memmove(lsrc, p->src, IPaddrlen);		memmove(p->src, p->dst, IPaddrlen);		memmove(p->dst, lsrc, IPaddrlen); */		goticmpkt6(icmp, bp, p->type);		break;	case NbrSolicit:		np = (Ndpkt*) p;		pktflags = 0;		switch (targettype(icmp->f, ipifc, np->target)) {		case t_unirany:			pktflags |= Oflag;			/* fall through */		case t_uniproxy: 			if(ipcmp(np->src, v6Unspecified) != 0) {				arpenter(icmp->f, V6, np->src, np->lnaddr, 8*np->olen-2, 0);				pktflags |= Sflag;			}			if(ipv6local(ipifc, lsrc)) {				icmpna(icmp->f, lsrc, 				   (ipcmp(np->src, v6Unspecified)==0)?v6allnodesL:np->src,				   np->target, ipifc->mac, pktflags); 			}			else				freeblist(bp);			break;		case t_unitent:			/* not clear what needs to be done. send up			 * an icmp mesg saying don't use this address? */		default:			freeblist(bp);		}		break;	case NbrAdvert:		np = (Ndpkt*) p;		/* if the target address matches one of the local interface 		 * address and the local interface address has tentative bit set, 		 * then insert into ARP table. this is so the duplication address 		 * detection part of ipconfig can discover duplication through 		 * the arp table		 */		lifc = iplocalonifc(ipifc, np->target);		if(lifc && lifc->tentative)			refresh = 0;		arpenter(icmp->f, V6, np->target, np->lnaddr, 8*np->olen-2, refresh);		freeblist(bp);		break;	case PacketTooBigV6:	default:		goticmpkt6(icmp, bp, 0);		break;	}	return;raise:	freeblist(bp);}inticmpstats6(Proto *icmp6, char *buf, int len){	Icmppriv6 *priv;	char *p, *e;	int i;	priv = icmp6->priv;	p = buf;	e = p+len;	for(i = 0; i < Nstats6; i++)		p = seprint(p, e, "%s: %lud\n", statnames6[i], priv->stats[i]);	for(i = 0; i <= Maxtype6; i++){		if(icmpnames6[i])			p = seprint(p, e, "%s: %lud %lud\n", icmpnames6[i], priv->in[i], priv->out[i]);/*		else			p = seprint(p, e, "%d: %lud %lud\n", i, priv->in[i], priv->out[i]);*/	}	return p - buf;}// need to import from icmp.cextern int	icmpstate(Conv *c, char *state, int n);extern char*	icmpannounce(Conv *c, char **argv, int argc);extern char*	icmpconnect(Conv *c, char **argv, int argc);extern void	icmpclose(Conv *c);voidicmp6init(Fs *fs){	Proto *icmp6 = smalloc(sizeof(Proto));	icmp6->priv = smalloc(sizeof(Icmppriv6));	icmp6->name = "icmpv6";	icmp6->connect = icmpconnect;	icmp6->announce = icmpannounce;	icmp6->state = icmpstate;	icmp6->create = icmpcreate6;	icmp6->close = icmpclose;	icmp6->rcv = icmpiput6;	icmp6->stats = icmpstats6;	icmp6->ctl = icmpctl6;	icmp6->advise = icmpadvise6;	icmp6->gc = nil;	icmp6->ipproto = ICMPv6;	icmp6->nc = 16;	icmp6->ptclsize = sizeof(Icmpcb6);	Fsproto(fs, icmp6);}

⌨️ 快捷键说明

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