From d9a750e1faacee3a5e42f322f475a455ca6f6956 Mon Sep 17 00:00:00 2001 From: ae Date: Thu, 6 Feb 2014 10:48:55 +0000 Subject: [PATCH] MFC r260702 (by melifaro): 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. git-svn-id: svn://svn.freebsd.org/base/stable/10@261545 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/netinet/ip_output.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 2838e76fe..7764bc380 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -200,6 +200,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; @@ -219,6 +226,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, RO_RTFREE(ro); ro->ro_lle = NULL; rte = NULL; + gw = dst; } if (rte == NULL && fwd_tag == NULL) { bzero(dst, sizeof(*dst)); -- 2.45.0