Skip to content

Commit a89c75a

Browse files
author
dlg
committed
have icmp_reflect use route sourceaddr.
this makes it behave like the in_pcb source address selection. ok claudio@ bluhm@
1 parent e85fcc4 commit a89c75a

File tree

1 file changed

+44
-25
lines changed

1 file changed

+44
-25
lines changed

sys/netinet/ip_icmp.c

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: ip_icmp.c,v 1.200 2025/06/12 20:37:59 deraadt Exp $ */
1+
/* $OpenBSD: ip_icmp.c,v 1.201 2025/06/20 05:08:07 dlg Exp $ */
22
/* $NetBSD: ip_icmp.c,v 1.19 1996/02/13 23:42:22 christos Exp $ */
33

44
/*
@@ -692,7 +692,8 @@ icmp_reflect(struct mbuf *m, struct mbuf **op, struct in_ifaddr *ia)
692692
struct ip *ip = mtod(m, struct ip *);
693693
struct mbuf *opts = NULL;
694694
struct sockaddr_in sin;
695-
struct rtentry *rt = NULL;
695+
struct rtentry *rt;
696+
struct in_addr ip_src = { INADDR_ANY };
696697
int optlen = (ip->ip_hl << 2) - sizeof(struct ip);
697698
u_int rtableid;
698699
u_int8_t pfflags;
@@ -709,10 +710,6 @@ icmp_reflect(struct mbuf *m, struct mbuf **op, struct in_ifaddr *ia)
709710
return (ELOOP);
710711
}
711712
rtableid = m->m_pkthdr.ph_rtableid;
712-
pfflags = m->m_pkthdr.pf.flags;
713-
m_resethdr(m);
714-
m->m_pkthdr.ph_rtableid = rtableid;
715-
m->m_pkthdr.pf.flags = pfflags & PF_TAG_GENERATED;
716713

717714
/*
718715
* If the incoming packet was addressed directly to us,
@@ -726,42 +723,64 @@ icmp_reflect(struct mbuf *m, struct mbuf **op, struct in_ifaddr *ia)
726723
sin.sin_addr = ip->ip_dst;
727724

728725
rt = rtalloc(sintosa(&sin), 0, rtableid);
729-
if (rtisvalid(rt) &&
730-
ISSET(rt->rt_flags, RTF_LOCAL|RTF_BROADCAST))
731-
ia = ifatoia(rt->rt_ifa);
732-
}
726+
if (rtisvalid(rt)) {
727+
if (ISSET(rt->rt_flags, RTF_LOCAL))
728+
ip_src = ip->ip_dst;
729+
else if (ISSET(rt->rt_flags, RTF_BROADCAST)) {
730+
ia = ifatoia(rt->rt_ifa);
731+
ip_src = ia->ia_addr.sin_addr;
732+
}
733+
}
734+
rtfree(rt);
735+
} else
736+
ip_src = ia->ia_addr.sin_addr;
733737

734738
/*
735739
* The following happens if the packet was not addressed to us.
736-
* Use the new source address and do a route lookup. If it fails
737-
* drop the packet as there is no path to the host.
740+
* If we're directly connected use the closest address, otherwise
741+
* try to use the sourceaddr from the routing table.
738742
*/
739-
if (ia == NULL) {
740-
rtfree(rt);
741-
743+
if (ip_src.s_addr == INADDR_ANY) {
742744
memset(&sin, 0, sizeof(sin));
743745
sin.sin_len = sizeof(sin);
744746
sin.sin_family = AF_INET;
745747
sin.sin_addr = ip->ip_src;
746748

747749
/* keep packet in the original virtual instance */
748750
rt = rtalloc(sintosa(&sin), RT_RESOLVE, rtableid);
749-
if (rt == NULL) {
750-
ipstat_inc(ips_noroute);
751-
m_freem(m);
752-
return (EHOSTUNREACH);
751+
if (rtisvalid(rt) &&
752+
ISSET(rt->rt_flags, RTF_LLINFO|RTF_HOST)) {
753+
ia = ifatoia(rt->rt_ifa);
754+
ip_src = ia->ia_addr.sin_addr;
755+
} else {
756+
struct sockaddr *sourceaddr;
757+
struct ifaddr *ifa;
758+
759+
sourceaddr = rtable_getsource(rtableid, AF_INET);
760+
if (sourceaddr != NULL) {
761+
ifa = ifa_ifwithaddr(sourceaddr, rtableid);
762+
if (ifa != NULL &&
763+
ISSET(ifa->ifa_ifp->if_flags, IFF_UP))
764+
ip_src = satosin(sourceaddr)->sin_addr;
765+
}
753766
}
754-
755-
ia = ifatoia(rt->rt_ifa);
767+
rtfree(rt);
756768
}
757769

770+
/*
771+
* If the above didn't find an ip_src, ip_output() will try
772+
* and fill it in for us.
773+
*/
774+
775+
pfflags = m->m_pkthdr.pf.flags;
776+
777+
m_resethdr(m);
778+
m->m_pkthdr.ph_rtableid = rtableid;
779+
m->m_pkthdr.pf.flags = pfflags & PF_TAG_GENERATED;
758780
ip->ip_dst = ip->ip_src;
781+
ip->ip_src = ip_src;
759782
ip->ip_ttl = MAXTTL;
760783

761-
/* It is safe to dereference ``ia'' iff ``rt'' is valid. */
762-
ip->ip_src = ia->ia_addr.sin_addr;
763-
rtfree(rt);
764-
765784
if (optlen > 0) {
766785
u_char *cp;
767786
int opt, cnt;

0 commit comments

Comments
 (0)