ref: 834b7f36cf4da1f4c08d27f1db9e0eed8717c542
parent: 73e115aab038880a68c9f73b5c49d8fa12d0e5e2
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Dec 17 19:40:23 EST 2022
devip: fix icmp bugs icmpdontfrag() was not working properly, need to pass the gating source interface. in fact, we now always pass the source interface to all icmp*() functions, which is used to determine source ip address of the icmp reply. also dont generate a icmp response for packets going to non-unicast addresses (such as broadcast). increase the amount of icmp response payload, but keep icmp responses below the minimum ipv4 mtu (68 bytes). regularize icmpv6 function names. move icmp unreachable codes to icmpv6.c. provide the mtu value for icmppkttoobig6(). dont advise announced udp connections. avoid code duplication in icmp.c and icmpv6.c, by having single send function with type, code and arg parameters. maintain statistics for sent ipv4 icmp types. avoid route lookup in ipout*() by passing Routehint* to icmpnohost*(). iladvise()... more like ill advice.
--- a/sys/src/9/ip/arp.c
+++ b/sys/src/9/ip/arp.c
@@ -562,7 +562,7 @@
return;
send:
if(!waserror()){
- icmpns(f, src, SRC_UNI, targ, TARG_MULTI, ifc->mac);
+ icmpns6(f, src, SRC_UNI, targ, TARG_MULTI, ifc->mac);
poperror();
}
}
@@ -606,24 +606,27 @@
static void
drop(Fs *f, Block *bp)
{
- Block *next;
- Ipifc *ifc;
+ Routehint rh;
Route *r;
+ Ipifc *ifc;
+ Block *next;
for(; bp != nil; bp = next){
next = bp->list;
bp->list = nil;
+ rh.r = nil;
+ rh.a = nil;
if((bp->rp[0]&0xF0) == IP_VER4)
- r = v4lookup(f, ((Ip4hdr*)bp->rp)->src, ((Ip4hdr*)bp->rp)->dst, nil);
+ r = v4lookup(f, ((Ip4hdr*)bp->rp)->src, ((Ip4hdr*)bp->rp)->dst, &rh);
else
- r = v6lookup(f, ((Ip6hdr*)bp->rp)->src, ((Ip6hdr*)bp->rp)->dst, nil);
+ r = v6lookup(f, ((Ip6hdr*)bp->rp)->src, ((Ip6hdr*)bp->rp)->dst, &rh);
if(r != nil && (ifc = r->ifc) != nil && canrlock(ifc)){
if(!waserror()){
if((bp->rp[0]&0xF0) == IP_VER4)
- icmpnohost(f, ifc, bp);
+ icmpnohost(f, ifc, bp, &rh);
else
- icmphostunr6(f, ifc, bp, Icmp6_adr_unreach, (r->type & Runi) != 0);
+ icmpnohost6(f, ifc, bp, &rh);
poperror();
}
runlock(ifc);
--- a/sys/src/9/ip/esp.c
+++ b/sys/src/9/ip/esp.c
@@ -433,7 +433,7 @@
* pass the result up the spi's Conv's read queue.
*/
void
-espiput(Proto *esp, Ipifc*, Block *bp)
+espiput(Proto *esp, Ipifc *ifc, Block *bp)
{
int payload, nexthdr;
uchar *auth, *espspi;
@@ -462,7 +462,7 @@
qunlock(esp);
netlog(f, Logesp, "esp: no conv %I -> %I!%lud\n", vers.raddr,
vers.laddr, vers.spi);
- icmpnoconv(f, bp);
+ icmpnoconv(f, ifc, bp);
freeblist(bp);
return;
}
--- a/sys/src/9/ip/ethermedium.c
+++ b/sys/src/9/ip/ethermedium.c
@@ -712,7 +712,7 @@
return;
if(!lifc->tentative){
- icmpna(f, lifc->local, v6allnodesL, ip, ifc->mac, 1<<5);
+ icmpna6(f, lifc->local, v6allnodesL, ip, ifc->mac, 1<<5);
return;
}
@@ -726,7 +726,7 @@
remroute(f, a, IPallbits, v6Unspecified, IPallbits, ip, Rmulti, ifc, tdad);
nexterror();
}
- icmpns(f, 0, SRC_UNSPEC, ip, TARG_MULTI, ifc->mac);
+ icmpns6(f, 0, SRC_UNSPEC, ip, TARG_MULTI, ifc->mac);
poperror();
remroute(f, a, IPallbits, v6Unspecified, IPallbits, ip, Rmulti, ifc, tdad);
}
--- a/sys/src/9/ip/icmp.c
+++ b/sys/src/9/ip/icmp.c
@@ -66,7 +66,7 @@
ICMP_IPSIZE = 20,
ICMP_HDRSIZE = 8,
- MinAdvise = ICMP_IPSIZE+4, /* minimum needed for us to advise another protocol */
+ MinAdvise = IP4HDR+4, /* minimum needed for us to advise another protocol */
};
enum
@@ -212,93 +212,86 @@
return ipforme(f, addr) == Runi;
}
-void
-icmpttlexceeded(Fs *f, Ipifc *ifc, Block *bp)
+/*
+ * Send a ICMP packet back of type/code/arg in response to packet bp
+ * which was received on ifc. The route hint rh is valid for the
+ * reverse route.
+ */
+static void
+icmpsend(Fs *f, Ipifc *ifc, Block *bp, int type, int code, int arg, Routehint *rh)
{
- Block *nbp;
- Icmp *p, *np;
+ Proto *icmp;
uchar ia[IPv4addrlen];
+ Block *nbp;
+ Icmp *np, *p;
+ int sz, osz;
+ osz = BLEN(bp);
+ if(osz < IP4HDR)
+ return;
+
p = (Icmp *)bp->rp;
- if(isv4mcast(p->dst) || !ip4reply(f, p->src) || !ipv4local(ifc, ia, 0, p->src))
+ if(!ip4reply(f, p->dst) || !ip4reply(f, p->src) || !ipv4local(ifc, ia, 0, p->src))
return;
- netlog(f, Logicmp, "sending icmpttlexceeded %V -> src %V dst %V\n",
- ia, p->src, p->dst);
+ netlog(f, Logicmp, "icmpsend %s (%d) %d ia %V -> src %V dst %V\n",
+ icmpnames[type], type, code, ia, p->src, p->dst);
- nbp = allocb(ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8);
- nbp->wp += ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8;
+ sz = MIN(ICMP_IPSIZE + ICMP_HDRSIZE + osz, v4MINTU);
+ nbp = allocb(sz);
+ nbp->wp += sz;
+ memset(nbp->rp, 0, sz);
np = (Icmp *)nbp->rp;
np->vihl = IP_VER4;
memmove(np->src, ia, sizeof(np->src));
memmove(np->dst, p->src, sizeof(np->dst));
- memmove(np->data, bp->rp, ICMP_IPSIZE + 8);
- np->type = TimeExceed;
- np->code = 0;
+ memmove(np->data, bp->rp, sz - ICMP_IPSIZE - ICMP_HDRSIZE);
+ np->type = type;
+ np->code = code;
np->proto = IP_ICMPPROTO;
hnputs(np->icmpid, 0);
- hnputs(np->seq, 0);
+ hnputs(np->seq, arg);
memset(np->cksum, 0, sizeof(np->cksum));
hnputs(np->cksum, ptclcsum(nbp, ICMP_IPSIZE, blocklen(nbp) - ICMP_IPSIZE));
- ipoput4(f, nbp, nil, MAXTTL, DFLTTOS, nil);
-}
-static void
-icmpunreachable(Fs *f, Ipifc *ifc, Block *bp, int code, int seq)
-{
- Block *nbp;
- Icmp *p, *np;
- uchar ia[IPv4addrlen];
+ icmp = f->t2p[IP_ICMPPROTO];
+ ((Icmppriv*)icmp->priv)->out[type]++;
- p = (Icmp *)bp->rp;
- if(isv4mcast(p->dst) || !ip4reply(f, p->src))
- return;
+ if(rh != nil && rh->r != nil && (rh->r->type & Runi) != 0){
+ np = (Icmp *)nbp->rp;
+ np->vihl = IP_VER4|IP_HLEN4;
+ np->tos = DFLTTOS;
+ np->ttl = MAXTTL;
- if(ifc == nil){
- if(!ipforme(f, p->dst))
- return;
- memmove(ia, p->dst, sizeof(p->dst));
- } else {
- if(!ipv4local(ifc, ia, 0, p->src))
- return;
+ (*icmp->rcv)(icmp, ifc, nbp);
+ return;
}
- netlog(f, Logicmp, "sending icmpunreachable %V -> src %V dst %V\n",
- ia, p->src, p->dst);
+ ipoput4(f, nbp, nil, MAXTTL, DFLTTOS, rh);
+}
- nbp = allocb(ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8);
- nbp->wp += ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8;
- np = (Icmp *)nbp->rp;
- np->vihl = IP_VER4;
- memmove(np->src, ia, sizeof(np->src));
- memmove(np->dst, p->src, sizeof(np->dst));
- memmove(np->data, bp->rp, ICMP_IPSIZE + 8);
- np->type = Unreachable;
- np->code = code;
- np->proto = IP_ICMPPROTO;
- hnputs(np->icmpid, 0);
- hnputs(np->seq, seq);
- memset(np->cksum, 0, sizeof(np->cksum));
- hnputs(np->cksum, ptclcsum(nbp, ICMP_IPSIZE, blocklen(nbp) - ICMP_IPSIZE));
- ipoput4(f, nbp, nil, MAXTTL, DFLTTOS, nil);
+void
+icmpnohost(Fs *f, Ipifc *ifc, Block *bp, Routehint *rh)
+{
+ icmpsend(f, ifc, bp, Unreachable, 1, 0, rh);
}
void
-icmpnohost(Fs *f, Ipifc *ifc, Block *bp)
+icmpnoconv(Fs *f, Ipifc *ifc, Block *bp)
{
- icmpunreachable(f, ifc, bp, 1, 0);
+ icmpsend(f, ifc, bp, Unreachable, 3, 0, nil);
}
void
-icmpnoconv(Fs *f, Block *bp)
+icmpcantfrag(Fs *f, Ipifc *ifc, Block *bp, int mtu)
{
- icmpunreachable(f, nil, bp, 3, 0);
+ icmpsend(f, ifc, bp, Unreachable, 4, mtu, nil);
}
void
-icmpcantfrag(Fs *f, Block *bp, int mtu)
+icmpttlexceeded(Fs *f, Ipifc *ifc, Block *bp)
{
- icmpunreachable(f, nil, bp, 4, mtu);
+ icmpsend(f, ifc, bp, TimeExceed, 0, 0, nil);
}
static void
@@ -479,7 +472,7 @@
* and send the advice to ip4.
*/
void
-icmpproxyadvice(Fs *f, Block *bp, Ipifc *ifc, uchar *ip4)
+icmpproxyadvice(Fs *f, Ipifc *ifc, Block *bp, uchar *ip4)
{
Icmp *p;
int hop;
@@ -543,7 +536,7 @@
hnputs_csum(p->icmpid, q->forward.rport, p->cksum);
qunlock(icmp);
- icmpproxyadvice(icmp->f, bp, ifc, p->src);
+ icmpproxyadvice(icmp->f, ifc, bp, p->src);
return;
}
for(c = icmp->conv; (s = *c) != nil; c++){
--- a/sys/src/9/ip/icmp6.c
+++ b/sys/src/9/ip/icmp6.c
@@ -67,10 +67,22 @@
Maxtype6 = 137,
};
+/* icmpv6 unreachability codes */
enum {
- MinAdvise = IP6HDR+4, /* minimum needed for us to advise another protocol */
+ Icmp6_no_route = 0,
+ Icmp6_ad_prohib = 1,
+ Icmp6_out_src_scope = 2,
+ Icmp6_adr_unreach = 3,
+ Icmp6_port_unreach = 4,
+ Icmp6_gress_src_fail = 5,
+ Icmp6_rej_route = 6,
+ Icmp6_unknown = 7, /* our own invention for internal use */
};
+enum {
+ MinAdvise = IP6HDR+4, /* minimum needed for us to advise another protocol */
+};
+
/* on-the-wire packet formats */
typedef struct IPICMP IPICMP;
typedef struct Ndpkt Ndpkt;
@@ -346,7 +358,7 @@
* and tuni == TARG_UNI => neighbor reachability.
*/
void
-icmpns(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac)
+icmpns6(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac)
{
Block *nbp;
Ndpkt *np;
@@ -386,7 +398,7 @@
* sends out an ICMPv6 neighbor advertisement. pktflags == RSO flags.
*/
void
-icmpna(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags)
+icmpna6(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags)
{
Block *nbp;
Ndpkt *np;
@@ -414,108 +426,82 @@
ipoput6(f, nbp, nil, MAXTTL, DFLTTOS, nil);
}
-void
-icmphostunr6(Fs *f, Ipifc *ifc, Block *bp, int code, int tome)
+/*
+ * Send a ICMPv6 packet back of type/code/arg in response to packet bp
+ * which was received on ifc. The route hint rh is valid for the
+ * reverse route.
+ */
+static void
+icmpsend6(Fs *f, Ipifc *ifc, Block *bp, int type, int code, int arg, Routehint *rh)
{
- int osz = BLEN(bp);
- int sz = MIN(IPICMPSZ + osz, v6MINTU);
+ Proto *icmp;
+ uchar ia[IPaddrlen];
+ Ip6hdr *p;
Block *nbp;
IPICMP *np;
- Ip6hdr *p;
- Proto *icmp = f->t2p[ICMPv6];
- Icmppriv6 *ipriv = icmp->priv;
- uchar ia[IPaddrlen];
+ int sz, osz;
+ osz = BLEN(bp);
+ if(osz < IP6HDR)
+ return;
+
p = (Ip6hdr *)bp->rp;
if(isv6mcast(p->dst) || isv6mcast(p->src) || !ipv6local(ifc, ia, 0, p->src))
return;
- netlog(f, Logicmp, "send icmphostunr %I -> src %I dst %I\n",
- ia, p->src, p->dst);
+ netlog(f, Logicmp, "icmpsend6 %s (%d) %d ia %I -> src %I dst %I\n",
+ icmpnames6[type], type, code, ia, p->src, p->dst);
+ sz = MIN(IPICMPSZ + osz, v6MINTU);
nbp = newIPICMP(sz);
np = (IPICMP *)nbp->rp;
ipmove(np->src, ia);
ipmove(np->dst, p->src);
- np->type = UnreachableV6;
+ np->type = type;
np->code = code;
+ hnputs(np->icmpid, 0);
+ hnputs(np->seq, arg);
memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ);
set_cksum(nbp);
- ipriv->out[UnreachableV6]++;
- if(tome){
+ icmp = f->t2p[ICMPv6];
+ ((Icmppriv6*)icmp->priv)->out[type]++;
+
+ if(rh != nil && rh->r != nil && (rh->r->type & Runi) != 0){
np = (IPICMP *)nbp->rp;
np->vcf[0] = IP_VER6 | DFLTTOS>>4;
np->vcf[1] = DFLTTOS<<4;
np->ttl = MAXTTL;
- ipiput6(f, ifc, nbp);
+ (*icmp->rcv)(icmp, ifc, nbp);
return;
}
- ipoput6(f, nbp, nil, MAXTTL, DFLTTOS, nil);
+
+ ipoput6(f, nbp, nil, MAXTTL, DFLTTOS, rh);
}
void
-icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp)
+icmpnohost6(Fs *f, Ipifc *ifc, Block *bp, Routehint *rh)
{
- int osz = BLEN(bp);
- int sz = MIN(IPICMPSZ + osz, v6MINTU);
- Block *nbp;
- IPICMP *np;
- Ip6hdr *p;
- Proto *icmp = f->t2p[ICMPv6];
- Icmppriv6 *ipriv = icmp->priv;
- uchar ia[IPaddrlen];
+ icmpsend6(f, ifc, bp, UnreachableV6, Icmp6_adr_unreach, 0, rh);
+}
- p = (Ip6hdr *)bp->rp;
- if(isv6mcast(p->dst) || isv6mcast(p->src) || !ipv6local(ifc, ia, 0, p->src))
- return;
-
- netlog(f, Logicmp, "send icmpttlexceeded6 %I -> src %I dst %I\n",
- ia, p->src, p->dst);
-
- nbp = newIPICMP(sz);
- np = (IPICMP *) nbp->rp;
- ipmove(np->src, ia);
- ipmove(np->dst, p->src);
- np->type = TimeExceedV6;
- np->code = 0;
- memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ);
- set_cksum(nbp);
- ipriv->out[TimeExceedV6]++;
- ipoput6(f, nbp, nil, MAXTTL, DFLTTOS, nil);
+void
+icmpnoconv6(Fs *f, Ipifc *ifc, Block *bp)
+{
+ icmpsend6(f, ifc, bp, UnreachableV6, Icmp6_port_unreach, 0, nil);
}
void
-icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp)
+icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp)
{
- int osz = BLEN(bp);
- int sz = MIN(IPICMPSZ + osz, v6MINTU);
- Block *nbp;
- IPICMP *np;
- Ip6hdr *p;
- Proto *icmp = f->t2p[ICMPv6];
- Icmppriv6 *ipriv = icmp->priv;
- uchar ia[IPaddrlen];
+ icmpsend6(f, ifc, bp, TimeExceedV6, 0, 0, nil);
+}
- p = (Ip6hdr *)bp->rp;
- if(isv6mcast(p->dst) || isv6mcast(p->src) || !ipv6local(ifc, ia, 0, p->src))
- return;
-
- netlog(f, Logicmp, "send icmppkttoobig6 %I -> src %I dst %I\n",
- ia, p->src, p->dst);
-
- nbp = newIPICMP(sz);
- np = (IPICMP *)nbp->rp;
- ipmove(np->src, ia);
- ipmove(np->dst, p->src);
- np->type = PacketTooBigV6;
- np->code = 0;
- hnputl(np->icmpid, ifc->maxtu - ifc->m->hsize);
- memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ);
- set_cksum(nbp);
- ipriv->out[PacketTooBigV6]++;
- ipoput6(f, nbp, nil, MAXTTL, DFLTTOS, nil);
+void
+icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp, int mtu)
+{
+ icmpsend6(f, ifc, bp, PacketTooBigV6, 0, mtu, nil);
}
/*
@@ -771,7 +757,7 @@
pktflags |= Sflag;
} else
ipmove(ia, np->target);
- icmpna(icmp->f, ia, (pktflags & Sflag)? np->src: v6allnodesL,
+ icmpna6(icmp->f, ia, (pktflags & Sflag)? np->src: v6allnodesL,
np->target, ifc->mac, pktflags);
break;
case Tunitent:
--- a/sys/src/9/ip/il.c
+++ b/sys/src/9/ip/il.c
@@ -1004,7 +1004,7 @@
hnputs(ih->illen, IL_HDRSIZE);
ih->frag[0] = 0;
ih->frag[1] = 0;
- if(inih) {
+ if(inih != nil) {
hnputl(ih->dst, nhgetl(inih->src));
hnputl(ih->src, nhgetl(inih->dst));
hnputs(ih->ilsrc, nhgets(inih->ildst));
@@ -1317,39 +1317,41 @@
void
iladvise(Proto *il, Block *bp, Ipifc*, char *msg)
{
+ uchar source[IPaddrlen], dest[IPaddrlen];
+ ushort psource, pdest;
+ Iphash *iph;
Ilhdr *h;
Ilcb *ic;
- uchar source[IPaddrlen], dest[IPaddrlen];
- ushort psource;
- Conv *s, **p;
+ Conv *s;
- h = (Ilhdr*)(bp->rp);
+ if(BLEN(bp) < IL_IPSIZE+IL_HDRSIZE-8){
+ freeblist(bp);
+ return;
+ }
+ h = (Ilhdr*)(bp->rp);
v4tov6(dest, h->dst);
v4tov6(source, h->src);
+ pdest = nhgets(h->ildst);
psource = nhgets(h->ilsrc);
-
- /* Look for a connection, unfortunately the destination port is missing */
+ /* Look for a connection (source/dest reversed; this is the original packet we sent) */
qlock(il);
- for(p = il->conv; *p; p++) {
- s = *p;
- if(s->lport == psource)
- if(ipcmp(s->laddr, source) == 0)
- if(ipcmp(s->raddr, dest) == 0){
- if(s->ignoreadvice)
- break;
- qunlock(il);
- ic = (Ilcb*)s->ptcl;
- switch(ic->state){
- case Ilsyncer:
- ilhangup(s, msg);
- break;
- }
- freeblist(bp);
- return;
- }
- }
+ iph = iphtlook(&((Ilpriv*)il->priv)->ht, dest, pdest, source, psource);
+ if(iph == nil || iph->match != IPmatchexact)
+ goto raise;
+ s = iphconv(iph);
+ if(s->ignoreadvice || s->state == Announced)
+ goto raise;
+ qlock(s);
+ qunlock(il);
+ ic = (Ilcb*)s->ptcl;
+ if(ic->state == Ilsyncer)
+ ilhangup(s, msg);
+ qunlock(s);
+ freeblist(bp);
+ return;
+raise:
qunlock(il);
freeblist(bp);
}
--- a/sys/src/9/ip/ip.c
+++ b/sys/src/9/ip/ip.c
@@ -167,7 +167,7 @@
if(eh->frag[0] & (IP_DF>>8)){
ip->stats[FragFails]++;
ip->stats[OutDiscards]++;
- icmpcantfrag(f, bp, medialen);
+ icmpcantfrag(f, gating!=nil? gating: ifc, bp, medialen);
netlog(f, Logip, "%V -> %V: can't fragment with DF flag set\n", eh->src, eh->dst);
goto raise;
}
--- a/sys/src/9/ip/ip.h
+++ b/sys/src/9/ip/ip.h
@@ -61,6 +61,7 @@
IP_FO= 0x1fff, /* v4: Fragment offset */
IP4HDR= IP_HLEN4<<2, /* sizeof(Ip4hdr) */
IP_MAX= 64*1024, /* Max. Internet packet size, v4 & v6 */
+ v4MINTU= 68, /* The minimum MTU for IPv4 is 68 bytes */
/* 2^Lroot trees in the root table */
Lroot= 10,
@@ -737,11 +738,11 @@
* ip.c
*/
extern void iprouting(Fs*, int);
-extern void icmpnohost(Fs*, Ipifc*, Block*);
-extern void icmpnoconv(Fs*, Block*);
-extern void icmpcantfrag(Fs*, Block*, int);
+extern void icmpnohost(Fs*, Ipifc*, Block*, Routehint*);
+extern void icmpnoconv(Fs*, Ipifc*, Block*);
+extern void icmpcantfrag(Fs*, Ipifc*, Block*, int);
extern void icmpttlexceeded(Fs*, Ipifc*, Block*);
-extern void icmpproxyadvice(Fs *, Block*, Ipifc*, uchar*);
+extern void icmpproxyadvice(Fs*, Ipifc*, Block*, uchar*);
extern ushort ipcsum(uchar*);
extern void ipiput4(Fs*, Ipifc*, Block*);
--- a/sys/src/9/ip/ipv6.c
+++ b/sys/src/9/ip/ipv6.c
@@ -117,7 +117,7 @@
* needed for nat.
*/
ip->stats[OutDiscards]++;
- icmppkttoobig6(f, ifc, bp);
+ icmppkttoobig6(f, gating, bp, medialen);
netlog(f, Logip, "%I -> %I: gated pkts not fragmented\n", eh->src, eh->dst);
goto raise;
}
--- a/sys/src/9/ip/ipv6.h
+++ b/sys/src/9/ip/ipv6.h
@@ -66,16 +66,6 @@
/* various prefix lengths */
SOLN_PREF_LEN = 13,
- /* icmpv6 unreachability codes */
- Icmp6_no_route = 0,
- Icmp6_ad_prohib = 1,
- Icmp6_out_src_scope = 2,
- Icmp6_adr_unreach = 3,
- Icmp6_port_unreach = 4,
- Icmp6_gress_src_fail = 5,
- Icmp6_rej_route = 6,
- Icmp6_unknown = 7, /* our own invention for internal use */
-
/* various flags & constants */
v6MINTU = 1280,
IP6HDR = 40, /* sizeof(Ip6hdr) = 8 + 2*16 */
@@ -179,8 +169,9 @@
extern int v6aLpreflen;
void ipv62smcast(uchar *, uchar *);
-void icmpns(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac);
-void icmpna(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags);
+void icmpns6(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac);
+void icmpna6(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags);
+void icmpnohost6(Fs *f, Ipifc *ifc, Block *bp, Routehint *rh);
+void icmpnoconv6(Fs *f, Ipifc *ifc, Block *bp);
void icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp);
-void icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp);
-void icmphostunr6(Fs *f, Ipifc *ifc, Block *bp, int code, int tome);
+void icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp, int mtu);
--- a/sys/src/9/ip/rudp.c
+++ b/sys/src/9/ip/rudp.c
@@ -514,7 +514,7 @@
laddr, lport);
uh->Unused = ottl;
hnputs(uh->udpplen, olen);
- icmpnoconv(f, bp);
+ icmpnoconv(f, ifc, bp);
freeblist(bp);
return;
}
--- a/sys/src/9/ip/tcp.c
+++ b/sys/src/9/ip/tcp.c
@@ -3243,7 +3243,7 @@
/* Look for a connection (source/dest reversed; this is the original packet we sent) */
qlock(tcp);
iph = iphtlook(&((Tcppriv*)tcp->priv)->ht, dest, pdest, source, psource);
- if(iph == nil)
+ if(iph == nil || iph->match != IPmatchexact)
goto raise;
if(iph->trans){
Translation *q;
@@ -3259,11 +3259,11 @@
hnputs(h4->tcpsport, q->forward.rport);
qunlock(tcp);
- icmpproxyadvice(tcp->f, bp, ifc, h4->tcpsrc);
+ icmpproxyadvice(tcp->f, ifc, bp, h4->tcpsrc);
return;
}
s = iphconv(iph);
- if(s->ignoreadvice || s->state == Closed)
+ if(s->ignoreadvice || s->state == Announced || s->state == Closed)
goto raise;
qlock(s);
qunlock(tcp);
--- a/sys/src/9/ip/udp.c
+++ b/sys/src/9/ip/udp.c
@@ -405,10 +405,10 @@
switch(version){
case V4:
- icmpnoconv(f, bp);
+ icmpnoconv(f, ifc, bp);
break;
case V6:
- icmphostunr6(f, ifc, bp, Icmp6_port_unreach, 0);
+ icmpnoconv6(f, ifc, bp);
break;
default:
panic("udpiput2: version %d", version);
@@ -572,7 +572,7 @@
/* Look for a connection (source/dest reversed; this is the original packet we sent) */
qlock(udp);
iph = iphtlook(&((Udppriv*)udp->priv)->ht, dest, pdest, source, psource);
- if(iph == nil)
+ if(iph == nil || iph->match != IPmatchexact)
goto raise;
if(iph->trans){
Translation *q;
@@ -588,11 +588,11 @@
hnputs(h4->udpsport, q->forward.rport);
qunlock(udp);
- icmpproxyadvice(udp->f, bp, ifc, h4->udpsrc);
+ icmpproxyadvice(udp->f, ifc, bp, h4->udpsrc);
return;
}
s = iphconv(iph);
- if(s->ignoreadvice)
+ if(s->ignoreadvice || s->state == Announced)
goto raise;
qlock(s);
qunlock(udp);