- Make ip_rtaddr() global, and use it to look up the correct source
address in icmp_reflect(). - Two new "struct icmpstat" members: icps_badaddr and icps_noroute. PR: kern/31575 Obtained from: BSD/OS MFC after: 1 week
This commit is contained in:
parent
6759374681
commit
bd7142087b
@ -57,6 +57,8 @@ struct icmpstat {
|
||||
u_long icps_inhist[ICMP_MAXTYPE + 1];
|
||||
u_long icps_bmcastecho; /* b/mcast echo requests dropped */
|
||||
u_long icps_bmcasttstamp; /* b/mcast tstamp requests dropped */
|
||||
u_long icps_badaddr; /* bad return address */
|
||||
u_long icps_noroute; /* no route back */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -109,7 +109,7 @@ int icmpprintfs = 0;
|
||||
#endif
|
||||
|
||||
static void icmp_reflect __P((struct mbuf *));
|
||||
static void icmp_send __P((struct mbuf *, struct mbuf *));
|
||||
static void icmp_send __P((struct mbuf *, struct mbuf *, struct route *));
|
||||
static int ip_next_mtu __P((int, int));
|
||||
|
||||
extern struct protosw inetsw[];
|
||||
@ -589,11 +589,13 @@ icmp_reflect(m)
|
||||
struct in_addr t;
|
||||
struct mbuf *opts = 0;
|
||||
int optlen = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof(struct ip);
|
||||
struct route *ro = NULL, rt;
|
||||
|
||||
if (!in_canforward(ip->ip_src) &&
|
||||
((ntohl(ip->ip_src.s_addr) & IN_CLASSA_NET) !=
|
||||
(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))) {
|
||||
m_freem(m); /* Bad return address */
|
||||
icmpstat.icps_badaddr++;
|
||||
goto done; /* Ip_output() will check for broadcast */
|
||||
}
|
||||
t = ip->ip_dst;
|
||||
@ -618,26 +620,13 @@ icmp_reflect(m)
|
||||
goto match;
|
||||
}
|
||||
}
|
||||
icmpdst.sin_addr = t;
|
||||
ia = (struct in_ifaddr *)ifaof_ifpforaddr(
|
||||
(struct sockaddr *)&icmpdst, m->m_pkthdr.rcvif);
|
||||
/*
|
||||
* The following happens if the packet was not addressed to us,
|
||||
* and was received on an interface with no IP address:
|
||||
* We find the first AF_INET address on the first non-loopback
|
||||
* interface.
|
||||
*/
|
||||
if (ia == NULL)
|
||||
TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link)
|
||||
if ((ia->ia_ifp->if_flags & IFF_LOOPBACK) == 0)
|
||||
break;
|
||||
|
||||
/*
|
||||
* If we still didn't find an address, punt. We could have an
|
||||
* interface up and (and receiving packets) with no address.
|
||||
*/
|
||||
ro = &rt;
|
||||
bzero(ro, sizeof(*ro));
|
||||
ia = ip_rtaddr(ip->ip_dst, ro);
|
||||
/* We need a route to do anything useful. */
|
||||
if (ia == NULL) {
|
||||
m_freem(m);
|
||||
icmpstat.icps_noroute++;
|
||||
goto done;
|
||||
}
|
||||
match:
|
||||
@ -718,10 +707,12 @@ icmp_reflect(m)
|
||||
(unsigned)(m->m_len - sizeof(struct ip)));
|
||||
}
|
||||
m->m_flags &= ~(M_BCAST|M_MCAST);
|
||||
icmp_send(m, opts);
|
||||
icmp_send(m, opts, ro);
|
||||
done:
|
||||
if (opts)
|
||||
(void)m_free(opts);
|
||||
if (ro && ro->ro_rt)
|
||||
RTFREE(ro->ro_rt);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -729,14 +720,14 @@ icmp_reflect(m)
|
||||
* after supplying a checksum.
|
||||
*/
|
||||
static void
|
||||
icmp_send(m, opts)
|
||||
icmp_send(m, opts, rt)
|
||||
register struct mbuf *m;
|
||||
struct mbuf *opts;
|
||||
struct route *rt;
|
||||
{
|
||||
register struct ip *ip = mtod(m, struct ip *);
|
||||
register int hlen;
|
||||
register struct icmp *icp;
|
||||
struct route ro;
|
||||
|
||||
hlen = IP_VHL_HL(ip->ip_vhl) << 2;
|
||||
m->m_data += hlen;
|
||||
@ -755,10 +746,7 @@ icmp_send(m, opts)
|
||||
buf, inet_ntoa(ip->ip_src));
|
||||
}
|
||||
#endif
|
||||
bzero(&ro, sizeof ro);
|
||||
(void) ip_output(m, opts, &ro, 0, NULL);
|
||||
if (ro.ro_rt)
|
||||
RTFREE(ro.ro_rt);
|
||||
(void) ip_output(m, opts, rt, 0, NULL);
|
||||
}
|
||||
|
||||
n_time
|
||||
|
@ -219,7 +219,6 @@ static struct mbuf *ip_reass __P((struct mbuf *, struct ipqhead *, struct ipq *,
|
||||
#else
|
||||
static struct mbuf *ip_reass __P((struct mbuf *, struct ipqhead *, struct ipq *));
|
||||
#endif
|
||||
static struct in_ifaddr *ip_rtaddr __P((struct in_addr));
|
||||
static void ipintr __P((void));
|
||||
|
||||
/*
|
||||
@ -1273,7 +1272,7 @@ ip_dooptions(m)
|
||||
if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0)
|
||||
ia = (INA)ifa_ifwithnet((SA)&ipaddr);
|
||||
} else
|
||||
ia = ip_rtaddr(ipaddr.sin_addr);
|
||||
ia = ip_rtaddr(ipaddr.sin_addr, &ipforward_rt);
|
||||
if (ia == 0) {
|
||||
type = ICMP_UNREACH;
|
||||
code = ICMP_UNREACH_SRCFAIL;
|
||||
@ -1311,7 +1310,8 @@ ip_dooptions(m)
|
||||
* use the incoming interface (should be same).
|
||||
*/
|
||||
if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 &&
|
||||
(ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {
|
||||
(ia = ip_rtaddr(ipaddr.sin_addr,
|
||||
&ipforward_rt)) == 0) {
|
||||
type = ICMP_UNREACH;
|
||||
code = ICMP_UNREACH_HOST;
|
||||
goto bad;
|
||||
@ -1399,30 +1399,31 @@ ip_dooptions(m)
|
||||
* Given address of next destination (final or next hop),
|
||||
* return internet address info of interface to be used to get there.
|
||||
*/
|
||||
static struct in_ifaddr *
|
||||
ip_rtaddr(dst)
|
||||
struct in_addr dst;
|
||||
struct in_ifaddr *
|
||||
ip_rtaddr(dst, rt)
|
||||
struct in_addr dst;
|
||||
struct route *rt;
|
||||
{
|
||||
register struct sockaddr_in *sin;
|
||||
|
||||
sin = (struct sockaddr_in *) &ipforward_rt.ro_dst;
|
||||
sin = (struct sockaddr_in *)&rt->ro_dst;
|
||||
|
||||
if (ipforward_rt.ro_rt == 0 ||
|
||||
!(ipforward_rt.ro_rt->rt_flags & RTF_UP) ||
|
||||
if (rt->ro_rt == 0 ||
|
||||
!(rt->ro_rt->rt_flags & RTF_UP) ||
|
||||
dst.s_addr != sin->sin_addr.s_addr) {
|
||||
if (ipforward_rt.ro_rt) {
|
||||
RTFREE(ipforward_rt.ro_rt);
|
||||
ipforward_rt.ro_rt = 0;
|
||||
if (rt->ro_rt) {
|
||||
RTFREE(rt->ro_rt);
|
||||
rt->ro_rt = 0;
|
||||
}
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_len = sizeof(*sin);
|
||||
sin->sin_addr = dst;
|
||||
|
||||
rtalloc_ign(&ipforward_rt, RTF_PRCLONING);
|
||||
rtalloc_ign(rt, RTF_PRCLONING);
|
||||
}
|
||||
if (ipforward_rt.ro_rt == 0)
|
||||
if (rt->ro_rt == 0)
|
||||
return ((struct in_ifaddr *)0);
|
||||
return (ifatoia(ipforward_rt.ro_rt->rt_ifa));
|
||||
return (ifatoia(rt->ro_rt->rt_ifa));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1608,7 +1609,7 @@ ip_forward(m, srcrt)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ip_rtaddr(ip->ip_dst) == 0) {
|
||||
if (ip_rtaddr(ip->ip_dst, &ipforward_rt) == 0) {
|
||||
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0);
|
||||
return;
|
||||
} else
|
||||
|
@ -164,6 +164,8 @@ extern int (*ip_mforward) __P((struct ip *, struct ifnet *, struct mbuf *,
|
||||
struct ip_moptions *));
|
||||
int ip_output __P((struct mbuf *,
|
||||
struct mbuf *, struct route *, int, struct ip_moptions *));
|
||||
struct in_ifaddr *
|
||||
ip_rtaddr __P((struct in_addr, struct route *));
|
||||
void ip_savecontrol __P((struct inpcb *, struct mbuf **, struct ip *,
|
||||
struct mbuf *));
|
||||
void ip_slowtimo __P((void));
|
||||
|
@ -624,6 +624,8 @@ icmp_stats(u_long off __unused, char *name, int af __unused)
|
||||
printf(m, icmpstat.f, plural(icmpstat.f))
|
||||
#define p1a(f, m) if (icmpstat.f || sflag <= 1) \
|
||||
printf(m, icmpstat.f)
|
||||
#define p2(f, m) if (icmpstat.f || sflag <= 1) \
|
||||
printf(m, icmpstat.f, plurales(icmpstat.f))
|
||||
|
||||
p(icps_error, "\t%lu call%s to icmp_error\n");
|
||||
p(icps_oldicmp,
|
||||
@ -653,8 +655,11 @@ icmp_stats(u_long off __unused, char *name, int af __unused)
|
||||
icmpstat.icps_inhist[i]);
|
||||
}
|
||||
p(icps_reflect, "\t%lu message response%s generated\n");
|
||||
p2(icps_badaddr, "\t%lu invalid return address%s\n");
|
||||
p(icps_badaddr, "\t%lu no return route%s\n");
|
||||
#undef p
|
||||
#undef p1a
|
||||
#undef p2
|
||||
mib[3] = ICMPCTL_MASKREPL;
|
||||
len = sizeof i;
|
||||
if (sysctl(mib, 4, &i, &len, (void *)0, 0) < 0)
|
||||
|
Loading…
Reference in New Issue
Block a user