summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2022-12-18 00:40:23 +0000
committercinap_lenrek <cinap_lenrek@felloff.net>2022-12-18 00:40:23 +0000
commit834b7f36cf4da1f4c08d27f1db9e0eed8717c542 (patch)
treea5e139487e292868516c463d9d080c35052419a4
parent73e115aab038880a68c9f73b5c49d8fa12d0e5e2 (diff)
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.
-rw-r--r--sys/src/9/ip/arp.c17
-rw-r--r--sys/src/9/ip/esp.c4
-rw-r--r--sys/src/9/ip/ethermedium.c4
-rw-r--r--sys/src/9/ip/icmp.c107
-rw-r--r--sys/src/9/ip/icmp6.c130
-rw-r--r--sys/src/9/ip/il.c52
-rw-r--r--sys/src/9/ip/ip.c2
-rw-r--r--sys/src/9/ip/ip.h9
-rw-r--r--sys/src/9/ip/ipv6.c2
-rw-r--r--sys/src/9/ip/ipv6.h19
-rw-r--r--sys/src/9/ip/rudp.c2
-rw-r--r--sys/src/9/ip/tcp.c6
-rw-r--r--sys/src/9/ip/udp.c10
13 files changed, 170 insertions, 194 deletions
diff --git a/sys/src/9/ip/arp.c b/sys/src/9/ip/arp.c
index c1dce39c0..74d36b1ee 100644
--- a/sys/src/9/ip/arp.c
+++ b/sys/src/9/ip/arp.c
@@ -562,7 +562,7 @@ ndpsendsol(Fs *f, Arpent *a)
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 @@ rxmt(Arp *arp)
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);
diff --git a/sys/src/9/ip/esp.c b/sys/src/9/ip/esp.c
index 447254a1c..f3ba10c59 100644
--- a/sys/src/9/ip/esp.c
+++ b/sys/src/9/ip/esp.c
@@ -433,7 +433,7 @@ espkick(void *x)
* 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 @@ espiput(Proto *esp, Ipifc*, Block *bp)
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;
}
diff --git a/sys/src/9/ip/ethermedium.c b/sys/src/9/ip/ethermedium.c
index 6a7b19bdd..999a65b5f 100644
--- a/sys/src/9/ip/ethermedium.c
+++ b/sys/src/9/ip/ethermedium.c
@@ -712,7 +712,7 @@ etherareg(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *ip)
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 @@ etherareg(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *ip)
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);
}
diff --git a/sys/src/9/ip/icmp.c b/sys/src/9/ip/icmp.c
index c4168605b..2b8218a51 100644
--- a/sys/src/9/ip/icmp.c
+++ b/sys/src/9/ip/icmp.c
@@ -66,7 +66,7 @@ enum {
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 @@ ip4me(Fs *f, uchar ip4[4])
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 @@ raise:
* 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 @@ icmpadvise(Proto *icmp, Block *bp, Ipifc *ifc, char *msg)
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++){
diff --git a/sys/src/9/ip/icmp6.c b/sys/src/9/ip/icmp6.c
index bfcfcee92..99c44134d 100644
--- a/sys/src/9/ip/icmp6.c
+++ b/sys/src/9/ip/icmp6.c
@@ -67,8 +67,20 @@ enum {
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 */
@@ -346,7 +358,7 @@ mkechoreply6(Block *bp, Ipifc *ifc)
* 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 @@ icmpns(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac)
* 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 @@ icmpna(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags)
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];
-
- 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);
+ icmpsend6(f, ifc, bp, UnreachableV6, Icmp6_adr_unreach, 0, rh);
}
void
-icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp)
+icmpnoconv6(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];
-
- p = (Ip6hdr *)bp->rp;
- if(isv6mcast(p->dst) || isv6mcast(p->src) || !ipv6local(ifc, ia, 0, p->src))
- return;
+ icmpsend6(f, ifc, bp, UnreachableV6, Icmp6_port_unreach, 0, nil);
+}
- netlog(f, Logicmp, "send icmppkttoobig6 %I -> src %I dst %I\n",
- ia, p->src, p->dst);
+void
+icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp)
+{
+ icmpsend6(f, ifc, bp, TimeExceedV6, 0, 0, nil);
+}
- 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 @@ icmpiput6(Proto *icmp, Ipifc *ifc, Block *bp)
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:
diff --git a/sys/src/9/ip/il.c b/sys/src/9/ip/il.c
index 4bf21eb26..d6db1d44b 100644
--- a/sys/src/9/ip/il.c
+++ b/sys/src/9/ip/il.c
@@ -1004,7 +1004,7 @@ ilsendctl(Conv *ipc, Ilhdr *inih, int type, ulong id, ulong ack, int ilspec)
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 @@ ilfreeq(Ilcb *ic)
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);
}
diff --git a/sys/src/9/ip/ip.c b/sys/src/9/ip/ip.c
index 751decffb..a8d2e3836 100644
--- a/sys/src/9/ip/ip.c
+++ b/sys/src/9/ip/ip.c
@@ -167,7 +167,7 @@ ipoput4(Fs *f, Block *bp, Ipifc *gating, int ttl, int tos, Routehint *rh)
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;
}
diff --git a/sys/src/9/ip/ip.h b/sys/src/9/ip/ip.h
index f535367ce..8742b6309 100644
--- a/sys/src/9/ip/ip.h
+++ b/sys/src/9/ip/ip.h
@@ -61,6 +61,7 @@ enum
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 @@ extern char* ipifcremove6(Ipifc *ifc, char**argv, int argc);
* 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*);
diff --git a/sys/src/9/ip/ipv6.c b/sys/src/9/ip/ipv6.c
index 4c79b004e..a47b520e6 100644
--- a/sys/src/9/ip/ipv6.c
+++ b/sys/src/9/ip/ipv6.c
@@ -117,7 +117,7 @@ ipoput6(Fs *f, Block *bp, Ipifc *gating, int ttl, int tos, Routehint *rh)
* 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;
}
diff --git a/sys/src/9/ip/ipv6.h b/sys/src/9/ip/ipv6.h
index b4ad9c5cd..578fefb1a 100644
--- a/sys/src/9/ip/ipv6.h
+++ b/sys/src/9/ip/ipv6.h
@@ -66,16 +66,6 @@ enum {
/* 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 v6aNpreflen;
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);
diff --git a/sys/src/9/ip/rudp.c b/sys/src/9/ip/rudp.c
index 726e4286f..f1aafc3d9 100644
--- a/sys/src/9/ip/rudp.c
+++ b/sys/src/9/ip/rudp.c
@@ -514,7 +514,7 @@ rudpiput(Proto *rudp, Ipifc *ifc, Block *bp)
laddr, lport);
uh->Unused = ottl;
hnputs(uh->udpplen, olen);
- icmpnoconv(f, bp);
+ icmpnoconv(f, ifc, bp);
freeblist(bp);
return;
}
diff --git a/sys/src/9/ip/tcp.c b/sys/src/9/ip/tcp.c
index a5b1c5f2a..bd4616d93 100644
--- a/sys/src/9/ip/tcp.c
+++ b/sys/src/9/ip/tcp.c
@@ -3243,7 +3243,7 @@ tcpadvise(Proto *tcp, Block *bp, Ipifc *ifc, char *msg)
/* 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 @@ tcpadvise(Proto *tcp, Block *bp, Ipifc *ifc, char *msg)
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);
diff --git a/sys/src/9/ip/udp.c b/sys/src/9/ip/udp.c
index 9e8d82b8e..3977e2202 100644
--- a/sys/src/9/ip/udp.c
+++ b/sys/src/9/ip/udp.c
@@ -405,10 +405,10 @@ Noconv:
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 @@ udpadvise(Proto *udp, Block *bp, Ipifc *ifc, char *msg)
/* 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 @@ udpadvise(Proto *udp, Block *bp, Ipifc *ifc, char *msg)
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);