From cfe5212a8b36139b260e85fe117efef6bbbc5a4b Mon Sep 17 00:00:00 2001 From: ru Date: Fri, 30 Nov 2001 10:40:28 +0000 Subject: - 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 --- sys/netinet/icmp_var.h | 2 ++ sys/netinet/ip_icmp.c | 40 ++++++++++++++-------------------------- sys/netinet/ip_input.c | 33 +++++++++++++++++---------------- sys/netinet/ip_var.h | 2 ++ usr.bin/netstat/inet.c | 5 +++++ 5 files changed, 40 insertions(+), 42 deletions(-) diff --git a/sys/netinet/icmp_var.h b/sys/netinet/icmp_var.h index 814e932..4038c42 100644 --- a/sys/netinet/icmp_var.h +++ b/sys/netinet/icmp_var.h @@ -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 */ }; /* diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 62bcd7e..dba581f 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -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 @@ match: (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 @@ done: * 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 diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 17e3103..475b837 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -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 @@ nosourcerouting: 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 @@ nosourcerouting: * 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 @@ bad: * 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 diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 2a84b38..d8f7a0b 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -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)); diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c index beb227e..b95bad7 100644 --- a/usr.bin/netstat/inet.c +++ b/usr.bin/netstat/inet.c @@ -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) -- cgit v1.1