summaryrefslogtreecommitdiff
path: root/sys/src/9/ip/icmp.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2021-09-26 18:43:29 +0000
committercinap_lenrek <cinap_lenrek@felloff.net>2021-09-26 18:43:29 +0000
commitd43d79bda454212f92fcec1ad4d049ecdc66e043 (patch)
tree983e8499b34d465e1e0ec6b12ce5a5a3d84b39ef /sys/src/9/ip/icmp.c
parent1cff923af4dbcaaab515cc04ea40c559eab7830f (diff)
devip: implement ipv4 arp timeout with icmp host unreachable notification
The IPv4 ARP cache used to indefinitely buffer packets in the Arpent hold list. This is bad in case of a router, because it opens a 1 second (retransmit time) window to leak all the to be forwarded packets. This change makes the ipv4 arp code path similar to the IPv6 neighbour solicitation path, using the retransmit process to time out old entries (after 3 arp retransmits => 3 seconds). A new function arpcontinue() has been added that unifies the point when we schedule the (ipv6 sol retransmit) / (ipv4 arp timeout) and reduce the hold queue to the last packet and unlock the cache. As a bonus, we also now send a icmp host unreachable notification for the dropped packets.
Diffstat (limited to 'sys/src/9/ip/icmp.c')
-rw-r--r--sys/src/9/ip/icmp.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/sys/src/9/ip/icmp.c b/sys/src/9/ip/icmp.c
index 93f0cd173..b17054c4c 100644
--- a/sys/src/9/ip/icmp.c
+++ b/sys/src/9/ip/icmp.c
@@ -242,22 +242,34 @@ icmpttlexceeded(Fs *f, Ipifc *ifc, Block *bp)
}
static void
-icmpunreachable(Fs *f, Block *bp, int code, int seq)
+icmpunreachable(Fs *f, Ipifc *ifc, Block *bp, int code, int seq)
{
Block *nbp;
Icmp *p, *np;
+ uchar ia[IPv4addrlen];
p = (Icmp *)bp->rp;
- if(!ip4me(f, p->dst) || !ip4reply(f, p->src))
+ if(!ip4reply(f, p->src))
return;
- netlog(f, Logicmp, "sending icmpnoconv -> %V\n", p->src);
+ 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;
+ }
+
+ netlog(f, Logicmp, "sending icmpunreachable %V -> src %V dst %V\n",
+ ia, p->src, p->dst);
+
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->src, p->dst, sizeof(np->src));
memmove(np->data, bp->rp, ICMP_IPSIZE + 8);
np->type = Unreachable;
np->code = code;
@@ -270,15 +282,21 @@ icmpunreachable(Fs *f, Block *bp, int code, int seq)
}
void
+icmpnohost(Fs *f, Ipifc *ifc, Block *bp)
+{
+ icmpunreachable(f, ifc, bp, 1, 0);
+}
+
+void
icmpnoconv(Fs *f, Block *bp)
{
- icmpunreachable(f, bp, 3, 0);
+ icmpunreachable(f, nil, bp, 3, 0);
}
void
icmpcantfrag(Fs *f, Block *bp, int mtu)
{
- icmpunreachable(f, bp, 4, mtu);
+ icmpunreachable(f, nil, bp, 4, mtu);
}
static void