📄 icmp6.c
字号:
#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 + -