diff options
author | melifaro <melifaro@FreeBSD.org> | 2014-01-16 11:50:00 +0000 |
---|---|---|
committer | melifaro <melifaro@FreeBSD.org> | 2014-01-16 11:50:00 +0000 |
commit | 479797d59ed717d502233535790a85aa1711028f (patch) | |
tree | 321694b96f152afaddb5eebdae2d01012cf1dbac | |
parent | 110a8053d6ba9cb2eced293507495d8335573a22 (diff) | |
download | FreeBSD-src-479797d59ed717d502233535790a85aa1711028f.zip FreeBSD-src-479797d59ed717d502233535790a85aa1711028f.tar.gz |
Fix ipfw fwd for IPv4 traffic broken by r249894.
Problem case:
Original lookup returns route with GW set, so gw points to
rte->rt_gateway.
After that we're changing dst and performing lookup another time.
Since fwd host is most probably directly reachable, resulting
rte does not contain rt_gateway, so gw is not set. Finally, we
end with packet transmitted to proper interface but wrong
link-layer address.
Found by: lstewart
Discussed with: ae,lstewart
MFC after: 2 weeks
Sponsored by: Yandex LLC
-rw-r--r-- | sys/netinet/ip_output.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index e3da758..5600ca7 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -202,6 +202,13 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, hlen = ip->ip_hl << 2; } + /* + * dst/gw handling: + * + * dst can be rewritten but always point to &ro->ro_dst + * gw is readonly but can be pointed either to dst OR rt_gatewy + * therefore we need restore GW if we're re-doing lookup + */ gw = dst = (struct sockaddr_in *)&ro->ro_dst; again: ia = NULL; @@ -221,6 +228,7 @@ again: RO_RTFREE(ro); ro->ro_lle = NULL; rte = NULL; + gw = dst; } if (rte == NULL && fwd_tag == NULL) { bzero(dst, sizeof(*dst)); |