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

📄 icmp6.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "../port/error.h"#include "ip.h"#include "ipv6.h"typedef struct ICMPpkt ICMPpkt;typedef struct IPICMP IPICMP;typedef struct Ndpkt Ndpkt;typedef struct NdiscC NdiscC;struct ICMPpkt {	uchar	type;	uchar	code;	uchar	cksum[2];	uchar	icmpid[2];	uchar	seq[2];};struct IPICMP {	Ip6hdr;	ICMPpkt;};struct NdiscC{	IPICMP;	uchar target[IPaddrlen];};struct Ndpkt{	NdiscC;	uchar otype;	uchar olen;	// length in units of 8 octets(incl type, code),				// 1 for IEEE 802 addresses	uchar lnaddr[6];	// link-layer address};enum {		// ICMPv6 types	EchoReply	= 0,	UnreachableV6	= 1,	PacketTooBigV6	= 2,	TimeExceedV6	= 3,	SrcQuench	= 4,	ParamProblemV6	= 4,	Redirect	= 5,	EchoRequest	= 8,	TimeExceed	= 11,	InParmProblem	= 12,	Timestamp	= 13,	TimestampReply	= 14,	InfoRequest	= 15,	InfoReply	= 16,	AddrMaskRequest = 17,	AddrMaskReply   = 18,	EchoRequestV6	= 128,	EchoReplyV6	= 129,	RouterSolicit	= 133,	RouterAdvert	= 134,	NbrSolicit	= 135,	NbrAdvert	= 136,	RedirectV6	= 137,	Maxtype6	= 137,};char *icmpnames6[Maxtype6+1] ={[EchoReply]		"EchoReply",[UnreachableV6]		"UnreachableV6",[PacketTooBigV6]	"PacketTooBigV6",[TimeExceedV6]		"TimeExceedV6",[SrcQuench]		"SrcQuench",[Redirect]		"Redirect",[EchoRequest]		"EchoRequest",[TimeExceed]		"TimeExceed",[InParmProblem]		"InParmProblem",[Timestamp]		"Timestamp",[TimestampReply]	"TimestampReply",[InfoRequest]		"InfoRequest",[InfoReply]		"InfoReply",[AddrMaskRequest]	"AddrMaskRequest",[AddrMaskReply]		"AddrMaskReply",[EchoRequestV6]		"EchoRequestV6",[EchoReplyV6]		"EchoReplyV6",[RouterSolicit]		"RouterSolicit",[RouterAdvert]		"RouterAdvert",[NbrSolicit]		"NbrSolicit",[NbrAdvert]		"NbrAdvert",[RedirectV6]		"RedirectV6",};enum{	InMsgs6,	InErrors6,	OutMsgs6,	CsumErrs6,	LenErrs6,	HlenErrs6,	HoplimErrs6,	IcmpCodeErrs6,	TargetErrs6,	OptlenErrs6,	AddrmxpErrs6,	RouterAddrErrs6,	Nstats6,};static char *statnames6[Nstats6] ={[InMsgs6]	"InMsgs",[InErrors6]	"InErrors",[OutMsgs6]	"OutMsgs",[CsumErrs6]	"CsumErrs",[LenErrs6]	"LenErrs",[HlenErrs6]	"HlenErrs",[HoplimErrs6]	"HoplimErrs",[IcmpCodeErrs6]	"IcmpCodeErrs",[TargetErrs6]	"TargetErrs",[OptlenErrs6]	"OptlenErrs",[AddrmxpErrs6]	"AddrmxpErrs",[RouterAddrErrs6]	"RouterAddrErrs",};typedef struct Icmppriv6{	ulong	stats[Nstats6];	/* message counts */	ulong	in[Maxtype6+1];	ulong	out[Maxtype6+1];} Icmppriv6;typedef struct Icmpcb6 {	QLock;	uchar headers;} Icmpcb6;static char *unreachcode[] ={[icmp6_no_route]	"no route to destination",[icmp6_ad_prohib]	"comm with destination administratively prohibited",[icmp6_unassigned]	"icmp unreachable: unassigned error code (2)",[icmp6_adr_unreach]	"address unreachable",[icmp6_port_unreach]	"port unreachable",[icmp6_unkn_code]	"icmp unreachable: unknown code",};enum {	ICMP_USEAD6	= 40,};enum {	Oflag	= 1<<5,	Sflag	= 1<<6,	Rflag	= 1<<7,};enum {	slladd	= 1,	tlladd	= 2,	prfinfo	= 3,	redhdr	= 4,	mtuopt	= 5,};static void icmpkick6(void *x, Block *bp);static voidicmpcreate6(Conv *c){	c->rq = qopen(64*1024, Qmsg, 0, c);	c->wq = qbypass(icmpkick6, c);}static voidset_cksum(Block *bp){	IPICMP *p = (IPICMP *)(bp->rp);	hnputl(p->vcf, 0);  // borrow IP header as pseudoheader	hnputs(p->ploadlen, blocklen(bp)-IPV6HDR_LEN);	p->proto = 0;	p->ttl = ICMPv6;	// ttl gets set later	hnputs(p->cksum, 0);	hnputs(p->cksum, ptclcsum(bp, 0, blocklen(bp)));	p->proto = ICMPv6;}static Block *newIPICMP(int packetlen){	Block	*nbp;	nbp = allocb(packetlen);	nbp->wp += packetlen;	memset(nbp->rp, 0, packetlen);	return nbp;}voidicmpadvise6(Proto *icmp, Block *bp, char *msg){	Conv	**c, *s;	IPICMP	*p;	ushort	recid;	p = (IPICMP *) bp->rp;	recid = nhgets(p->icmpid);	for(c = icmp->conv; *c; c++) {		s = *c;		if(s->lport == recid)		if(ipcmp(s->raddr, p->dst) == 0){			qhangup(s->rq, msg);			qhangup(s->wq, msg);			break;		}	}	freeblist(bp);}static voidicmpkick6(void *x, Block *bp){	Conv *c = x;	IPICMP *p;	uchar laddr[IPaddrlen], raddr[IPaddrlen];	Icmppriv6 *ipriv = c->p->priv;	Icmpcb6 *icb = (Icmpcb6*)c->ptcl;	if(bp == nil)		return;	if(icb->headers==6) {		/* get user specified addresses */		bp = pullupblock(bp, ICMP_USEAD6);		if(bp == nil)			return;		bp->rp += 8;		ipmove(laddr, bp->rp);		bp->rp += IPaddrlen;		ipmove(raddr, bp->rp);		bp->rp += IPaddrlen;		bp = padblock(bp, sizeof(Ip6hdr));	}	if(blocklen(bp) < sizeof(IPICMP)){		freeblist(bp);		return;	}	p = (IPICMP *)(bp->rp);	if(icb->headers == 6) {		ipmove(p->dst, raddr);		ipmove(p->src, laddr);	} else {		ipmove(p->dst, c->raddr);		ipmove(p->src, c->laddr);		hnputs(p->icmpid, c->lport);	}	set_cksum(bp);	p->vcf[0] = 0x06 << 4;	if(p->type <= Maxtype6)			ipriv->out[p->type]++;	ipoput6(c->p->f, bp, 0, c->ttl, c->tos, nil);}char*icmpctl6(Conv *c, char **argv, int argc){	Icmpcb6 *icb;	icb = (Icmpcb6*) c->ptcl;	if(argc==1) {		if(strcmp(argv[0], "headers")==0) {			icb->headers = 6;			return nil;		}	}	return "unknown control request";}static voidgoticmpkt6(Proto *icmp, Block *bp, int muxkey){	Conv	**c, *s;	IPICMP	*p = (IPICMP *)bp->rp;	ushort	recid; 	uchar 	*addr;	if(muxkey == 0) {		recid = nhgets(p->icmpid);		addr = p->src;	}	else {		recid = muxkey;		addr = p->dst;	}	for(c = icmp->conv; *c; c++){		s = *c;		if(s->lport == recid && ipcmp(s->raddr, addr) == 0){			bp = concatblock(bp);			if(bp != nil)				qpass(s->rq, bp);			return;		}	}	freeblist(bp);}static Block *mkechoreply6(Block *bp){	IPICMP *p = (IPICMP *)(bp->rp);	uchar	addr[IPaddrlen];	ipmove(addr, p->src);	ipmove(p->src, p->dst);	ipmove(p->dst, addr);	p->type = EchoReplyV6;	set_cksum(bp);	return bp;}/* * sends out an ICMPv6 neighbor solicitation * 	suni == SRC_UNSPEC or SRC_UNI,  *	tuni == TARG_MULTI => multicast for address resolution, * 	and tuni == TARG_UNI => neighbor reachability. */extern voidicmpns(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac){	Block	*nbp;	Ndpkt *np;	Proto *icmp = f->t2p[ICMPv6];	Icmppriv6 *ipriv = icmp->priv;	nbp = newIPICMP(sizeof(Ndpkt));	np = (Ndpkt*) nbp->rp;	if(suni == SRC_UNSPEC) 		memmove(np->src, v6Unspecified, IPaddrlen);	else 		memmove(np->src, src, IPaddrlen);	if(tuni == TARG_UNI)		memmove(np->dst, targ, IPaddrlen);	else		ipv62smcast(np->dst, targ);	np->type = NbrSolicit;	np->code = 0;	memmove(np->target, targ, IPaddrlen);	if(suni != SRC_UNSPEC) {		np->otype = SRC_LLADDRESS;		np->olen = 1;	/* 1+1+6 = 8 = 1 8-octet */		memmove(np->lnaddr, mac, sizeof(np->lnaddr));	}	else {		int r = sizeof(Ndpkt)-sizeof(NdiscC);		nbp->wp -= r;	}	set_cksum(nbp);	np = (Ndpkt*) nbp->rp;	np->ttl = HOP_LIMIT;	np->vcf[0] = 0x06 << 4;	ipriv->out[NbrSolicit]++;	netlog(f, Logicmp, "sending neighbor solicitation %I\n", targ);	ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);}/* * sends out an ICMPv6 neighbor advertisement. pktflags == RSO flags. */extern voidicmpna(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags){	Block	*nbp;	Ndpkt *np;	Proto *icmp = f->t2p[ICMPv6];	Icmppriv6 *ipriv = icmp->priv;	nbp = newIPICMP(sizeof(Ndpkt));	np = (Ndpkt*) nbp->rp;	memmove(np->src, src, IPaddrlen);	memmove(np->dst, dst, IPaddrlen);	np->type = NbrAdvert;	np->code = 0;	np->icmpid[0] = flags;	memmove(np->target, targ, IPaddrlen);	np->otype = TARGET_LLADDRESS;	np->olen = 1;		memmove(np->lnaddr, mac, sizeof(np->lnaddr));	set_cksum(nbp);	np = (Ndpkt*) nbp->rp;	np->ttl = HOP_LIMIT;	np->vcf[0] = 0x06 << 4;	ipriv->out[NbrAdvert]++;	netlog(f, Logicmp, "sending neighbor advertisement %I\n", src);	ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);}extern voidicmphostunr(Fs *f, Ipifc *ifc, Block *bp, int code, int free){	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)) 		goto clean;	nbp = newIPICMP(sz);	np = (IPICMP *) nbp->rp;	rlock(ifc);	if(ipv6anylocal(ifc, np->src)) {		netlog(f, Logicmp, "send icmphostunr -> s%I d%I\n", p->src, p->dst);	}	else {		netlog(f, Logicmp, "icmphostunr fail -> s%I d%I\n", p->src, p->dst);		freeblist(nbp);		if(free) 			goto clean;		else			return;	}	memmove(np->dst, p->src, IPaddrlen);	np->type = UnreachableV6;	np->code = code;	memmove(nbp->rp + sizeof(IPICMP), bp->rp, sz - sizeof(IPICMP));	set_cksum(nbp);

⌨️ 快捷键说明

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