shithub: riscv

Download patch

ref: 074b691f16faba137ab9cb48471fc3160b33da40
parent: 5f42bde60275e9a0c3d317ee1e052e1aefdcdb19
author: cinap_lenrek <[email protected]>
date: Tue Dec 13 17:23:01 EST 2022

devip: tcpmssclamp() to minimum of source and destination interface MTU

We used to only clamp to the MTU of the destination interface,
but this is wrong. We have to clamp to the minimum of both
source and destination.

For this, we change the gating argument type of ipoput4()
and ipoput6() from int to Ipifc* to pass the source interface.

--- a/sys/src/9/ip/esp.c
+++ b/sys/src/9/ip/esp.c
@@ -423,9 +423,9 @@
 	qunlock(c);
 	/* print("esp: pass down: %uld\n", BLEN(bp)); */
 	if (vers.version == V4)
-		ipoput4(c->p->f, bp, 0, c->ttl, c->tos, c);
+		ipoput4(c->p->f, bp, nil, c->ttl, c->tos, c);
 	else
-		ipoput6(c->p->f, bp, 0, c->ttl, c->tos, c);
+		ipoput6(c->p->f, bp, nil, c->ttl, c->tos, c);
 }
 
 /*
@@ -574,7 +574,7 @@
 
 /* called from icmp(v6) for unreachable hosts, time exceeded, etc. */
 void
-espadvise(Proto *esp, Block *bp, char *msg)
+espadvise(Proto *esp, Block *bp, Ipifc *, char *msg)
 {
 	Conv *c;
 	Versdep vers;
--- a/sys/src/9/ip/gre.c
+++ b/sys/src/9/ip/gre.c
@@ -435,7 +435,7 @@
 	memmove(gre->src, grec->coa, sizeof gre->dst);
 	memmove(gre->dst, grec->south, sizeof gre->dst);
 
-	ipoput4(c->p->f, copyblock(bp, BLEN(bp)), 0, gre->ttl - 1, gre->tos, nil);
+	ipoput4(c->p->f, copyblock(bp, BLEN(bp)), nil, gre->ttl - 1, gre->tos, nil);
 	grepdout++;
 	grebdout += BLEN(bp);
 
@@ -506,7 +506,7 @@
 	if(grec->ulsusp)
 		addring(&grec->ulbuffered, bp);
 	else{
-		ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil);
+		ipoput4(c->p->f, bp, nil, gre->ttl - 1, gre->tos, nil);
 		grepuout++;
 		grebuout += BLEN(bp);
 	}
@@ -777,7 +777,7 @@
 		gre = (GREhdr *)bp->rp;
 		qunlock(&grec->lock);
 
-		ipoput4(c->p->f, copyblock(bp, BLEN(bp)), 0, gre->ttl - 1, gre->tos, nil);
+		ipoput4(c->p->f, copyblock(bp, BLEN(bp)), nil, gre->ttl - 1, gre->tos, nil);
 
 		qlock(&grec->lock);
 		addring(&grec->dlpending, bp);
@@ -801,7 +801,7 @@
 		gre = (GREhdr *)bp->rp;
 
 		qunlock(&grec->lock);
-		ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil);
+		ipoput4(c->p->f, bp, nil, gre->ttl - 1, gre->tos, nil);
 		qlock(&grec->lock);
 	}
 	grec->ulsusp = 0;
@@ -843,7 +843,7 @@
 		memmove(gre->dst, grec->south, sizeof gre->dst);
 
 		qunlock(&grec->lock);
-		ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil);
+		ipoput4(c->p->f, bp, nil, gre->ttl - 1, gre->tos, nil);
 		qlock(&grec->lock);
 	}
 
@@ -853,7 +853,7 @@
 		memmove(gre->dst, grec->south, sizeof gre->dst);
 
 		qunlock(&grec->lock);
-		ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil);
+		ipoput4(c->p->f, bp, nil, gre->ttl - 1, gre->tos, nil);
 		qlock(&grec->lock);
 	}
 
@@ -864,7 +864,7 @@
 		memmove(gre->dst, grec->south, sizeof gre->dst);
 
 		qunlock(&grec->lock);
-		ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil);
+		ipoput4(c->p->f, bp, nil, gre->ttl - 1, gre->tos, nil);
 		qlock(&grec->lock);
 	}
 	qunlock(&grec->lock);
--- a/sys/src/9/ip/icmp.c
+++ b/sys/src/9/ip/icmp.c
@@ -185,7 +185,7 @@
 	memset(p->cksum, 0, sizeof(p->cksum));
 	hnputs(p->cksum, ptclcsum(bp, ICMP_IPSIZE, blocklen(bp) - ICMP_IPSIZE));
 	ipriv->stats[OutMsgs]++;
-	ipoput4(c->p->f, bp, 0, c->ttl, c->tos, nil);
+	ipoput4(c->p->f, bp, nil, c->ttl, c->tos, nil);
 }
 
 static int
@@ -240,7 +240,7 @@
 	hnputs(np->seq, 0);
 	memset(np->cksum, 0, sizeof(np->cksum));
 	hnputs(np->cksum, ptclcsum(nbp, ICMP_IPSIZE, blocklen(nbp) - ICMP_IPSIZE));
-	ipoput4(f, nbp, 0, MAXTTL, DFLTTOS, nil);
+	ipoput4(f, nbp, nil, MAXTTL, DFLTTOS, nil);
 }
 
 static void
@@ -280,7 +280,7 @@
 	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, 0, MAXTTL, DFLTTOS, nil);
+	ipoput4(f, nbp, nil, MAXTTL, DFLTTOS, nil);
 }
 
 void
@@ -302,7 +302,7 @@
 }
 
 static void
-goticmpkt(Proto *icmp, Block *bp)
+goticmpkt(Proto *icmp, Block *bp, Ipifc *ifc)
 {
 	uchar	dst[IPaddrlen], src[IPaddrlen];
 	ushort	recid;
@@ -331,7 +331,7 @@
 			q = nil;
 		qunlock(icmp);
 
-		ipoput4(icmp->f, bp, 1, hop - 1, p->tos, q);
+		ipoput4(icmp->f, bp, ifc, hop - 1, p->tos, q);
 		return;
 	}
 	for(c = icmp->conv; (s = *c) != nil; c++){
@@ -386,7 +386,7 @@
 };
 
 static void
-icmpiput(Proto *icmp, Ipifc*, Block *bp)
+icmpiput(Proto *icmp, Ipifc *ifc, Block *bp)
 {
 	int	n;
 	Icmp	*p;
@@ -426,7 +426,7 @@
 		if(r == nil)
 			goto raise;
 		ipriv->out[EchoReply]++;
-		ipoput4(icmp->f, r, 0, MAXTTL, DFLTTOS, nil);
+		ipoput4(icmp->f, r, nil, MAXTTL, DFLTTOS, nil);
 		break;
 	case TimeExceed:
 		if(p->code == 0){
@@ -433,7 +433,7 @@
 			snprint(msg = m2, sizeof m2, "ttl exceeded at %V", p->src);
 			goto Advise;
 		}
-		goticmpkt(icmp, bp);
+		goticmpkt(icmp, bp, ifc);
 		break;
 	case Unreachable:
 		if(p->code >= nelem(unreachcode)) {
@@ -455,7 +455,7 @@
 			pr = Fsrcvpcolx(icmp->f, p->proto);
 			if(pr != nil && pr->advise != nil) {
 				netlog(icmp->f, Logicmp, "advising %s!%V -> %V: %s\n", pr->name, p->src, p->dst, msg);
-				(*pr->advise)(pr, bp, msg);
+				(*pr->advise)(pr, bp, ifc, msg);
 				return;
 			}
 		}
@@ -462,7 +462,7 @@
 		bp->rp -= ICMP_IPSIZE+ICMP_HDRSIZE;
 		/* wet floor */
 	default:
-		goticmpkt(icmp, bp);
+		goticmpkt(icmp, bp, ifc);
 		break;
 	}
 	return;
@@ -479,7 +479,7 @@
  * and send the advice to ip4.
  */
 void
-icmpproxyadvice(Fs *f, Block *bp, uchar *ip4)
+icmpproxyadvice(Fs *f, Block *bp, Ipifc *ifc, uchar *ip4)
 {
 	Icmp	*p;
 	int	hop;
@@ -509,7 +509,7 @@
 	memset(p->cksum, 0, sizeof(p->cksum));
 	hnputs(p->cksum, ptclcsum(bp, ICMP_IPSIZE, blocklen(bp) - ICMP_IPSIZE));
 
-	ipoput4(f, bp, 1, hop - 1, p->tos, nil);
+	ipoput4(f, bp, ifc, hop - 1, p->tos, nil);
 	return;
 drop:
 	freeblist(bp);
@@ -516,7 +516,7 @@
 }
 
 static void
-icmpadvise(Proto *icmp, Block *bp, char *msg)
+icmpadvise(Proto *icmp, Block *bp, Ipifc *ifc, char *msg)
 {
 	uchar	dst[IPaddrlen], src[IPaddrlen];
 	ushort	recid;
@@ -543,7 +543,7 @@
 		hnputs_csum(p->icmpid, q->forward.rport, p->cksum);
 		qunlock(icmp);
 
-		icmpproxyadvice(icmp->f, bp, p->src);
+		icmpproxyadvice(icmp->f, bp, ifc, 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
@@ -216,7 +216,7 @@
 }
 
 static void
-icmpadvise6(Proto *icmp, Block *bp, char *msg)
+icmpadvise6(Proto *icmp, Block *bp, Ipifc *, char *msg)
 {
 	ushort recid;
 	Conv **c, *s;
@@ -281,7 +281,7 @@
 	set_cksum(bp);
 	if(p->type <= Maxtype6)
 		ipriv->out[p->type]++;
-	ipoput6(c->p->f, bp, 0, c->ttl, c->tos, nil);
+	ipoput6(c->p->f, bp, nil, c->ttl, c->tos, nil);
 }
 
 static char*
@@ -379,7 +379,7 @@
 	set_cksum(nbp);
 	ipriv->out[NbrSolicit]++;
 	netlog(f, Logicmp, "sending neighbor solicitation %I\n", targ);
-	ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
+	ipoput6(f, nbp, nil, MAXTTL, DFLTTOS, nil);
 }
 
 /*
@@ -411,7 +411,7 @@
 	set_cksum(nbp);
 	ipriv->out[NbrAdvert]++;
 	netlog(f, Logicmp, "sending neighbor advertisement %I\n", targ);
-	ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
+	ipoput6(f, nbp, nil, MAXTTL, DFLTTOS, nil);
 }
 
 void
@@ -452,7 +452,7 @@
 		ipiput6(f, ifc, nbp);
 		return;
 	}
-	ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
+	ipoput6(f, nbp, nil, MAXTTL, DFLTTOS, nil);
 }
 
 void
@@ -483,7 +483,7 @@
 	memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ);
 	set_cksum(nbp);
 	ipriv->out[TimeExceedV6]++;
-	ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
+	ipoput6(f, nbp, nil, MAXTTL, DFLTTOS, nil);
 }
 
 void
@@ -515,7 +515,7 @@
 	memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ);
 	set_cksum(nbp);
 	ipriv->out[PacketTooBigV6]++;
-	ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
+	ipoput6(f, nbp, nil, MAXTTL, DFLTTOS, nil);
 }
 
 /*
@@ -692,7 +692,7 @@
 		if(r == nil)
 			goto raise;
 		ipriv->out[EchoReply]++;
-		ipoput6(icmp->f, r, 0, MAXTTL, DFLTTOS, nil);
+		ipoput6(icmp->f, r, nil, MAXTTL, DFLTTOS, nil);
 		break;
 
 	case UnreachableV6:
@@ -724,7 +724,7 @@
 			pr = Fsrcvpcolx(icmp->f, p->proto);
 			if(pr != nil && pr->advise != nil) {
 				netlog(icmp->f, Logicmp, "advising %s!%I -> %I: %s\n", pr->name, p->src, p->dst, msg);
-				(*pr->advise)(pr, bp, msg);
+				(*pr->advise)(pr, bp, ifc, msg);
 				return;
 			}
 		}
--- a/sys/src/9/ip/igmp.c
+++ b/sys/src/9/ip/igmp.c
@@ -121,7 +121,7 @@
 	p->proto = IP_IGMPPROTO;
 	memmove(p->group, group+IPv4off, IPv4addrlen);
 	hnputs(p->igmpcksum, ptclcsum(bp, IGMP_IPHDRSIZE, IGMP_HDRSIZE));
-	ipoput4(f, bp, 0, 1, DFLTTOS, nil);	/* TTL of 1 */
+	ipoput4(f, bp, nil, 1, DFLTTOS, nil);	/* TTL of 1 */
 }
 
 static void
@@ -160,7 +160,7 @@
 	p->proto = IP_MLDPROTO;
 	hnputs(p->ploadlen, BLEN(bp) - IP6HDR);
 	
-	ipoput6(f, bp, 0, 1, DFLTTOS, nil);	/* TTL of 1 */
+	ipoput6(f, bp, nil, 1, DFLTTOS, nil);	/* TTL of 1 */
 }
 
 static void
--- a/sys/src/9/ip/il.c
+++ b/sys/src/9/ip/il.c
@@ -221,7 +221,7 @@
 void	ilackproc(void*);
 void	iloutoforder(Conv*, Ilhdr*, Block*);
 void	iliput(Proto*, Ipifc*, Block*);
-void	iladvise(Proto*, Block*, char*);
+void	iladvise(Proto*, Block*, Ipifc*, char*);
 int	ilnextqt(Ilcb*);
 void	ilcbinit(Ilcb*);
 int	later(ulong, ulong, char*);
@@ -415,7 +415,7 @@
 
 	if(later(NOW, ic->timeout, nil))
 		ilsettimeout(ic);
-	ipoput4(f, bp, 0, c->ttl, c->tos, c);
+	ipoput4(f, bp, nil, c->ttl, c->tos, c);
 	priv->stats[OutMsgs]++;
 }
 
@@ -842,7 +842,7 @@
 
 	ilbackoff(ic);
 
-	ipoput4(c->p->f, nb, 0, c->ttl, c->tos, c);
+	ipoput4(c->p->f, nb, nil, c->ttl, c->tos, c);
 
 	/* statistics */
 	ic->rxtot++;
@@ -1044,7 +1044,7 @@
 		iltype[ih->iltype], nhgetl(ih->ilid), nhgetl(ih->ilack), 
 		nhgets(ih->ilsrc), nhgets(ih->ildst));
 
-	return ipoput4(ipc->p->f, bp, 0, ttl, tos, ipc);
+	return ipoput4(ipc->p->f, bp, nil, ttl, tos, ipc);
 }
 
 void
@@ -1078,7 +1078,7 @@
 	if(ilcksum)
 		hnputs(ih->ilsum, ptclcsum(bp, IL_IPSIZE, IL_HDRSIZE));
 
-	ipoput4(f, bp, 0, MAXTTL, DFLTTOS, nil);
+	ipoput4(f, bp, nil, MAXTTL, DFLTTOS, nil);
 }
 
 void
@@ -1315,7 +1315,7 @@
 }
 
 void
-iladvise(Proto *il, Block *bp, char *msg)
+iladvise(Proto *il, Block *bp, Ipifc*, char *msg)
 {
 	Ilhdr *h;
 	Ilcb *ic;		
--- a/sys/src/9/ip/ip.c
+++ b/sys/src/9/ip/ip.c
@@ -85,7 +85,7 @@
 }
 
 int
-ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos, Routehint *rh)
+ipoput4(Fs *f, Block *bp, Ipifc *gating, int ttl, int tos, Routehint *rh)
 {
 	Ipifc *ifc;
 	uchar *gate;
@@ -135,9 +135,12 @@
 		goto raise;
 
 	medialen = ifc->maxtu - ifc->m->hsize;
-	if(gating)
-		tcpmssclamp(bp->rp, BLEN(bp), medialen);
-	else {
+	if(gating != nil) {
+		int mtu = gating->maxtu - gating->m->hsize;
+		if(medialen < mtu)
+			mtu = medialen;
+		tcpmssclamp(bp->rp, BLEN(bp), mtu);
+	} else {
 		eh->vihl = IP_VER4|IP_HLEN4;
 		eh->tos = tos;
 	}
@@ -146,7 +149,7 @@
 	/* If we dont need to fragment just send it */
 	if(len <= medialen) {
 		hnputs(eh->length, len);
-		if(!gating){
+		if(gating == nil){
 			hnputs(eh->id, incref(&ip->id4));
 			eh->frag[0] = 0;
 			eh->frag[1] = 0;
@@ -375,7 +378,7 @@
 		}
 
 		ip->stats[ForwDatagrams]++;
-		ipoput4(f, bp, 1, hop - 1, h->tos, &rh);
+		ipoput4(f, bp, ifc, hop - 1, h->tos, &rh);
 		return;
 	}
 
--- a/sys/src/9/ip/ip.h
+++ b/sys/src/9/ip/ip.h
@@ -432,7 +432,7 @@
 	void		(*close)(Conv*);
 	void		(*rcv)(Proto*, Ipifc*, Block*);
 	char*		(*ctl)(Conv*, char**, int);
-	void		(*advise)(Proto*, Block*, char*);
+	void		(*advise)(Proto*, Block*, Ipifc*, char*);
 	int		(*stats)(Proto*, char*, int);
 	int		(*local)(Conv*, char*, int);
 	int		(*remote)(Conv*, char*, int);
@@ -741,13 +741,13 @@
 extern void	icmpnoconv(Fs*, Block*);
 extern void	icmpcantfrag(Fs*, Block*, int);
 extern void	icmpttlexceeded(Fs*, Ipifc*, Block*);
-extern void	icmpproxyadvice(Fs *, Block*, uchar*);
+extern void	icmpproxyadvice(Fs *, Block*, Ipifc*, uchar*);
 
 extern ushort	ipcsum(uchar*);
 extern void	ipiput4(Fs*, Ipifc*, Block*);
 extern void	ipiput6(Fs*, Ipifc*, Block*);
-extern int	ipoput4(Fs*, Block*, int, int, int, Routehint*);
-extern int	ipoput6(Fs*, Block*, int, int, int, Routehint*);
+extern int	ipoput4(Fs*, Block*, Ipifc*, int, int, Routehint*);
+extern int	ipoput6(Fs*, Block*, Ipifc*, int, int, Routehint*);
 extern int	ipstats(Fs*, char*, int);
 extern ushort	ptclbsum(uchar*, int);
 extern ushort	ptclcsum(Block*, int, int);
--- a/sys/src/9/ip/ipmux.c
+++ b/sys/src/9/ip/ipmux.c
@@ -661,9 +661,9 @@
 		Ip4hdr *ih4 = (Ip4hdr*)(bp->rp);
 
 		if((ih4->vihl & 0xF0) != IP_VER6)
-			ipoput4(c->p->f, bp, 0, ih4->ttl, ih4->tos, nil);
+			ipoput4(c->p->f, bp, nil, ih4->ttl, ih4->tos, nil);
 		else
-			ipoput6(c->p->f, bp, 0, ((Ip6hdr*)ih4)->ttl, 0, nil);
+			ipoput6(c->p->f, bp, nil, ((Ip6hdr*)ih4)->ttl, 0, nil);
 	}
 }
 
--- a/sys/src/9/ip/ipv6.c
+++ b/sys/src/9/ip/ipv6.c
@@ -38,7 +38,7 @@
 }
 
 int
-ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos, Routehint *rh)
+ipoput6(Fs *f, Block *bp, Ipifc *gating, int ttl, int tos, Routehint *rh)
 {
 	int medialen, len, chunk, uflen, flen, seglen, lid, offset, fragoff;
 	int morefrags, blklen, rv = 0;
@@ -89,9 +89,12 @@
 		goto raise;
 
 	medialen = ifc->maxtu - ifc->m->hsize;
-	if(gating)
-		tcpmssclamp(bp->rp, BLEN(bp), medialen);
-	else {
+	if(gating != nil){
+		int mtu = gating->maxtu - gating->m->hsize;
+		if(medialen < mtu)
+			mtu = medialen;
+		tcpmssclamp(bp->rp, BLEN(bp), mtu);
+	} else {
 		eh->vcf[0] = IP_VER6;
 		eh->vcf[0] |= tos >> 4;
 		eh->vcf[1]  = tos << 4;
@@ -107,7 +110,7 @@
 		return 0;
 	}
 
-	if(gating && !ifc->reassemble) {
+	if(gating != nil && !ifc->reassemble) {
 		/*
 		 * v6 intermediate nodes are not supposed to fragment pkts;
 		 * we fragment if ifc->reassemble is turned on; an exception
@@ -294,7 +297,7 @@
 		ip->stats[ForwDatagrams]++;
 		h = (Ip6hdr*)bp->rp;
 		tos = (h->vcf[0]&0x0F)<<2 | (h->vcf[1]&0xF0)>>2;
-		ipoput6(f, bp, 1, hop - 1, tos, &rh);
+		ipoput6(f, bp, ifc, hop - 1, tos, &rh);
 		return;
 	}
 
--- a/sys/src/9/ip/rudp.c
+++ b/sys/src/9/ip/rudp.c
@@ -314,7 +314,7 @@
  *  randomly don't send packets
  */
 static void
-doipoput(Conv *c, Fs *f, Block *bp, int x, int ttl, int tos)
+doipoput(Conv *c, Fs *f, Block *bp, int ttl, int tos)
 {
 	Rudpcb *ucb;
 
@@ -322,7 +322,7 @@
 	if(ucb->randdrop && nrand(100) < ucb->randdrop)
 		freeblist(bp);
 	else
-		ipoput4(f, bp, x, ttl, tos, nil);
+		ipoput4(f, bp, nil, ttl, tos, nil);
 }
 
 int
@@ -437,7 +437,7 @@
 	DPRINT("sent: %lud/%lud, %lud/%lud\n", 
 		r->sndseq, r->sndgen, r->rcvseq, r->rcvgen);
 
-	doipoput(c, f, bp, 0, c->ttl, c->tos);
+	doipoput(c, f, bp, c->ttl, c->tos);
 
 	if(waserror()) {
 		relput(r);
@@ -622,7 +622,7 @@
 }
 
 void
-rudpadvise(Proto *rudp, Block *bp, char *msg)
+rudpadvise(Proto *rudp, Block *bp, Ipifc *, char *msg)
 {
 	Udphdr *h;
 	uchar source[IPaddrlen], dest[IPaddrlen];
@@ -987,7 +987,7 @@
 	hnputs(uh->udpcksum, ptclcsum(bp, UDP_IPHDR, UDP_RHDRSIZE));
 
 	DPRINT("sendack: %lud/%lud, %lud/%lud\n", 0L, r->sndgen, r->rcvseq, r->rcvgen);
-	doipoput(c, f, bp, 0, c->ttl, c->tos);
+	doipoput(c, f, bp, c->ttl, c->tos);
 }
 
 
@@ -1047,5 +1047,5 @@
 	upriv->rxmits++;
 	np = copyblock(r->unacked, blocklen(r->unacked));
 	DPRINT("rxmit r->ackrvcd+1 = %lud\n", r->ackrcvd+1);
-	doipoput(c, f, np, 0, c->ttl, c->tos);
+	doipoput(c, f, np, c->ttl, c->tos);
 }
--- a/sys/src/9/ip/tcp.c
+++ b/sys/src/9/ip/tcp.c
@@ -1391,10 +1391,10 @@
 	switch(version) {
 	case V4:
 		hbp = htontcp4(seg, nil, &ph4, nil);
-		return ipoput4(tcp->f, hbp, 0, MAXTTL, DFLTTOS, rh);
+		return ipoput4(tcp->f, hbp, nil, MAXTTL, DFLTTOS, rh);
 	case V6:
 		hbp = htontcp6(seg, nil, &ph6, nil);
-		return ipoput6(tcp->f, hbp, 0, MAXTTL, DFLTTOS, rh);
+		return ipoput6(tcp->f, hbp, nil, MAXTTL, DFLTTOS, rh);
 	}
 	return -1;
 }
@@ -1428,12 +1428,12 @@
 			case V4:
 				tcb->protohdr.tcp4hdr.vihl = IP_VER4;
 				hbp = htontcp4(&seg, nil, &tcb->protohdr.tcp4hdr, tcb);
-				ipoput4(s->p->f, hbp, 0, s->ttl, s->tos, s);
+				ipoput4(s->p->f, hbp, nil, s->ttl, s->tos, s);
 				break;
 			case V6:
 				tcb->protohdr.tcp6hdr.vcf[0] = IP_VER6;
 				hbp = htontcp6(&seg, nil, &tcb->protohdr.tcp6hdr, tcb);
-				ipoput6(s->p->f, hbp, 0, s->ttl, s->tos, s);
+				ipoput6(s->p->f, hbp, nil, s->ttl, s->tos, s);
 				break;
 			default:
 				panic("tcphangup: version %d", s->ipversion);
@@ -1512,10 +1512,10 @@
 	switch(lp->version) {
 	case V4:
 		hbp = htontcp4(&seg, nil, &ph4, nil);
-		return ipoput4(tcp->f, hbp, 0, MAXTTL, DFLTTOS, &rh);
+		return ipoput4(tcp->f, hbp, nil, MAXTTL, DFLTTOS, &rh);
 	case V6:
 		hbp = htontcp6(&seg, nil, &ph6, nil);
-		return ipoput6(tcp->f, hbp, 0, MAXTTL, DFLTTOS, &rh);
+		return ipoput6(tcp->f, hbp, nil, MAXTTL, DFLTTOS, &rh);
 	}
 	return -1;
 }
@@ -2061,7 +2061,7 @@
 }
 
 static void
-tcpiput(Proto *tcp, Ipifc*, Block *bp)
+tcpiput(Proto *tcp, Ipifc *ifc, Block *bp)
 {
 	Tcp seg;
 	Tcp4hdr *h4;
@@ -2184,7 +2184,7 @@
 		hnputs_csum(h4->tcpdst+2, nhgets(q->forward.raddr+IPv4off+2), h4->tcpcksum);
 		hnputs_csum(h4->tcpdport, q->forward.rport, h4->tcpcksum);
 		qunlock(tcp);
-		ipoput4(f, bp, 1, hop - 1, h4->tos, q);
+		ipoput4(f, bp, ifc, hop - 1, h4->tos, q);
 		return;
 	}
 	s = iphconv(iph);
@@ -2757,11 +2757,11 @@
 
 		switch(version){
 		case V4:
-			if(ipoput4(f, hbp, 0, s->ttl, s->tos, s) < 0)
+			if(ipoput4(f, hbp, nil, s->ttl, s->tos, s) < 0)
 				localclose(s, Enoroute);
 			break;
 		case V6:
-			if(ipoput6(f, hbp, 0, s->ttl, s->tos, s) < 0)
+			if(ipoput6(f, hbp, nil, s->ttl, s->tos, s) < 0)
 				localclose(s, Enoroute);
 			break;
 		}
@@ -2811,13 +2811,13 @@
 		/* Build header, link data and compute cksum */
 		tcb->protohdr.tcp4hdr.vihl = IP_VER4;
 		hbp = htontcp4(&seg, dbp, &tcb->protohdr.tcp4hdr, tcb);
-		return ipoput4(s->p->f, hbp, 0, s->ttl, s->tos, s);
+		return ipoput4(s->p->f, hbp, nil, s->ttl, s->tos, s);
 	}
 	else {
 		/* Build header, link data and compute cksum */
 		tcb->protohdr.tcp6hdr.vcf[0] = IP_VER6;
 		hbp = htontcp6(&seg, dbp, &tcb->protohdr.tcp6hdr, tcb);
-		return ipoput6(s->p->f, hbp, 0, s->ttl, s->tos, s);
+		return ipoput6(s->p->f, hbp, nil, s->ttl, s->tos, s);
 	}
 }
 
@@ -3214,7 +3214,7 @@
 }
 
 static void
-tcpadvise(Proto *tcp, Block *bp, char *msg)
+tcpadvise(Proto *tcp, Block *bp, Ipifc *ifc, char *msg)
 {
 	Tcp4hdr *h4;
 	Tcp6hdr *h6;
@@ -3259,7 +3259,7 @@
 		hnputs(h4->tcpsport, q->forward.rport);
 		qunlock(tcp);
 
-		icmpproxyadvice(tcp->f, bp, h4->tcpsrc);
+		icmpproxyadvice(tcp->f, bp, ifc, h4->tcpsrc);
 		return;
 	}
 	s = iphconv(iph);
--- a/sys/src/9/ip/udp.c
+++ b/sys/src/9/ip/udp.c
@@ -267,7 +267,7 @@
 			csum = 0xffff;	/* -0 */
 		hnputs(uh4->udpcksum, csum);
 		uh4->vihl = IP_VER4;
-		ipoput4(f, bp, 0, c->ttl, c->tos, rh);
+		ipoput4(f, bp, nil, c->ttl, c->tos, rh);
 		break;
 
 	case V6:
@@ -303,7 +303,7 @@
 		uh6->viclfl[0] = IP_VER6;
 		hnputs(uh6->len, ptcllen);
 		uh6->nextheader = IP_UDPPROTO;
-		ipoput6(f, bp, 0, c->ttl, c->tos, rh);
+		ipoput6(f, bp, nil, c->ttl, c->tos, rh);
 		break;
 
 	default:
@@ -433,7 +433,7 @@
 		if(memcmp(uh4->udpsrc, q->forward.laddr+IPv4off, IPv4addrlen) != 0)
 			q = nil;
 		qunlock(udp);
-		ipoput4(f, bp, 1, hop - 1, uh4->tos, q);
+		ipoput4(f, bp, ifc, hop - 1, uh4->tos, q);
 		return;
 	}
 	c = iphconv(iph);
@@ -545,7 +545,7 @@
 }
 
 void
-udpadvise(Proto *udp, Block *bp, char *msg)
+udpadvise(Proto *udp, Block *bp, Ipifc *ifc, char *msg)
 {
 	Udp4hdr *h4;
 	Udp6hdr *h6;
@@ -588,7 +588,7 @@
 		hnputs(h4->udpsport, q->forward.rport);
 		qunlock(udp);
 
-		icmpproxyadvice(udp->f, bp, h4->udpsrc);
+		icmpproxyadvice(udp->f, bp, ifc, h4->udpsrc);
 		return;
 	}
 	s = iphconv(iph);