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