diff --git a/sys/netinet/in_rmx.c b/sys/netinet/in_rmx.c index b762c29e8684..b33094e5443a 100644 --- a/sys/netinet/in_rmx.c +++ b/sys/netinet/in_rmx.c @@ -134,13 +134,6 @@ in_addroute(void *v_arg, void *n_arg, struct radix_node_head *head, } } - /* - * If the new route created successfully, and we are forwarding, - * flush any cached routes to avoid using a stale value. - */ - if (ret != NULL && ipforwarding) - ip_forward_cacheinval(); - return ret; } diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c index e5960dfcfd03..0767634849de 100644 --- a/sys/netinet/ip_fw2.c +++ b/sys/netinet/ip_fw2.c @@ -1160,7 +1160,6 @@ send_pkt(struct ipfw_flow_id *id, u_int32_t seq, u_int32_t ack, int flags) struct mbuf *m; struct ip *ip; struct tcphdr *tcp; - struct route sro; /* fake route */ MGETHDR(m, M_DONTWAIT, MT_HEADER); if (m == 0) @@ -1226,12 +1225,8 @@ send_pkt(struct ipfw_flow_id *id, u_int32_t seq, u_int32_t ack, int flags) */ ip->ip_ttl = ip_defttl; ip->ip_len = m->m_pkthdr.len; - bzero (&sro, sizeof (sro)); - ip_rtaddr(ip->ip_dst, &sro); m->m_flags |= M_SKIP_FIREWALL; - ip_output(m, NULL, &sro, 0, NULL, NULL); - if (sro.ro_rt) - RTFREE(sro.ro_rt); + ip_output(m, NULL, NULL, 0, NULL, NULL); } /* diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 9c5d4d0d2f32..12c6c42081c9 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -120,7 +120,7 @@ int icmpprintfs = 0; #endif static void icmp_reflect(struct mbuf *); -static void icmp_send(struct mbuf *, struct mbuf *, struct route *); +static void icmp_send(struct mbuf *, struct mbuf *); static int ip_next_mtu(int, int); extern struct protosw inetsw[]; @@ -615,7 +615,6 @@ icmp_reflect(m) struct in_addr t; struct mbuf *opts = 0; int optlen = (ip->ip_hl << 2) - sizeof(struct ip); - struct route *ro = NULL, rt; if (!in_canforward(ip->ip_src) && ((ntohl(ip->ip_src.s_addr) & IN_CLASSA_NET) != @@ -626,8 +625,6 @@ icmp_reflect(m) } t = ip->ip_dst; ip->ip_dst = ip->ip_src; - ro = &rt; - bzero(ro, sizeof(*ro)); /* * If the incoming packet was addressed directly to us, * use dst as the src for the reply. Otherwise (broadcast @@ -648,7 +645,7 @@ icmp_reflect(m) goto match; } } - ia = ip_rtaddr(ip->ip_dst, ro); + ia = ip_rtaddr(ip->ip_dst); /* We need a route to do anything useful. */ if (ia == NULL) { m_freem(m); @@ -738,12 +735,10 @@ match: } m_tag_delete_nonpersistent(m); m->m_flags &= ~(M_BCAST|M_MCAST); - icmp_send(m, opts, ro); + icmp_send(m, opts); done: if (opts) (void)m_free(opts); - if (ro && ro->ro_rt) - RTFREE(ro->ro_rt); } /* @@ -751,10 +746,9 @@ done: * after supplying a checksum. */ static void -icmp_send(m, opts, rt) +icmp_send(m, opts) register struct mbuf *m; struct mbuf *opts; - struct route *rt; { register struct ip *ip = mtod(m, struct ip *); register int hlen; @@ -777,7 +771,7 @@ icmp_send(m, opts, rt) buf, inet_ntoa(ip->ip_src)); } #endif - (void) ip_output(m, opts, rt, 0, NULL, NULL); + (void) ip_output(m, opts, NULL, 0, NULL, NULL); } n_time diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 025ef0c3b397..2b1ca63c678e 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -212,52 +212,6 @@ int fw_one_pass = 1; /* Dummynet hooks */ ip_dn_io_t *ip_dn_io_ptr; -/* - * One deep route cache for ip forwarding. This is done - * very inefficiently. We don't care as it's about to be - * replaced by something better. - */ -static struct rtcache { - struct route rc_ro; /* most recently used route */ - struct mtx rc_mtx; /* update lock for cache */ -} ip_fwdcache; - -#define RTCACHE_LOCK() mtx_lock(&ip_fwdcache.rc_mtx) -#define RTCACHE_UNLOCK() mtx_unlock(&ip_fwdcache.rc_mtx) -#define RTCACHE_LOCK_INIT() \ - mtx_init(&ip_fwdcache.rc_mtx, "route cache", NULL, MTX_DEF) -#define RTCACHE_LOCK_ASSERT() mtx_assert(&ip_fwdcache.rc_mtx, MA_OWNED) - -/* - * Get a copy of the current route cache contents. - */ -#define RTCACHE_GET(_ro) do { \ - struct rtentry *rt; \ - RTCACHE_LOCK(); \ - *(_ro) = ip_fwdcache.rc_ro; \ - if ((rt = (_ro)->ro_rt) != NULL) { \ - RT_LOCK(rt); \ - RT_ADDREF(rt); \ - RT_UNLOCK(rt); \ - } \ - RTCACHE_UNLOCK(); \ -} while (0) - -/* - * Update the cache contents. - */ -#define RTCACHE_UPDATE(_ro) do { \ - struct rtentry *rt; \ - RTCACHE_LOCK(); \ - rt = ip_fwdcache.rc_ro.ro_rt; \ - if ((_ro)->ro_rt != rt) { \ - ip_fwdcache.rc_ro = *(_ro); \ - if (rt) \ - RTFREE(rt); \ - } \ - RTCACHE_UNLOCK(); \ -} while (0) - /* * XXX this is ugly -- the following two global variables are * used to store packet state while it travels through the stack. @@ -282,7 +236,7 @@ static struct ip_srcrt { static void save_rte(u_char *, struct in_addr); static int ip_dooptions(struct mbuf *m, int, struct sockaddr_in *next_hop); -static void ip_forward(struct mbuf *m, struct route *, int srcrt, +static void ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop); static void ip_freef(struct ipqhead *, struct ipq *); static struct mbuf *ip_reass(struct mbuf *, struct ipqhead *, @@ -323,9 +277,6 @@ ip_init() for (i = 0; i < IPREASS_NHASH; i++) TAILQ_INIT(&ipq[i]); - bzero(&ip_fwdcache, sizeof(ip_fwdcache)); - RTCACHE_LOCK_INIT(); - maxnipq = nmbclusters / 32; maxfragsperpacket = 16; @@ -337,22 +288,6 @@ ip_init() netisr_register(NETISR_IP, ip_input, &ipintrq, NETISR_MPSAFE); } -/* - * Invalidate any cached route used for forwarding. - */ -void -ip_forward_cacheinval(void) -{ - struct rtentry *rt; - - RTCACHE_LOCK(); - rt = ip_fwdcache.rc_ro.ro_rt; - ip_fwdcache.rc_ro.ro_rt = 0; - if (rt != NULL) - RTFREE(rt); - RTCACHE_UNLOCK(); -} - /* * Ip input routine. Checksum and byte swap header. If fragmented * try to reassemble. Process options. Pass to next level. @@ -370,8 +305,7 @@ ip_input(struct mbuf *m) struct in_addr pkt_dst; u_int32_t divert_info = 0; /* packet divert/tee info */ struct ip_fw_args args; - struct route cro; /* copy of cached route */ - int srcrt = 0; /* forward by ``src routing'' */ + int dchg = 0; /* dest changed after fw */ #ifdef PFIL_HOOKS struct in_addr odst; /* original dst address */ #endif @@ -566,7 +500,7 @@ iphack: if (m == NULL) /* consumed by filter */ return; ip = mtod(m, struct ip *); - srcrt = (odst.s_addr != ip->ip_dst.s_addr); + dchg = (odst.s_addr != ip->ip_dst.s_addr); #endif /* PFIL_HOOKS */ if (fw_enable && IPFW_LOADED) { @@ -802,8 +736,7 @@ pass: goto bad; } #endif /* FAST_IPSEC */ - RTCACHE_GET(&cro); - ip_forward(m, &cro, srcrt, args.next_hop); + ip_forward(m, dchg, args.next_hop); } return; @@ -1419,14 +1352,6 @@ ip_dooptions(struct mbuf *m, int pass, struct sockaddr_in *next_hop) struct in_addr *sin, dst; n_time ntime; struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; - struct route cro; /* copy of cached route */ - - /* - * Grab a copy of the route cache in case we need - * to update to reflect source routing or the like. - * Could optimize this to do it later... - */ - RTCACHE_GET(&cro); dst = ip->ip_dst; cp = (u_char *)(ip + 1); @@ -1546,7 +1471,7 @@ dropit: if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0) ia = (INA)ifa_ifwithnet((SA)&ipaddr); } else - ia = ip_rtaddr(ipaddr.sin_addr, &cro); + ia = ip_rtaddr(ipaddr.sin_addr); if (ia == 0) { type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; @@ -1588,7 +1513,7 @@ dropit: * use the incoming interface (should be same). */ if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 && - (ia = ip_rtaddr(ipaddr.sin_addr, &cro)) == 0) { + (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) { type = ICMP_UNREACH; code = ICMP_UNREACH_HOST; goto bad; @@ -1668,7 +1593,7 @@ dropit: } } if (forward && ipforwarding) { - ip_forward(m, &cro, 1, next_hop); + ip_forward(m, 1, next_hop); return (1); } return (0); @@ -1683,30 +1608,26 @@ bad: * return internet address info of interface to be used to get there. */ struct in_ifaddr * -ip_rtaddr(dst, rt) +ip_rtaddr(dst) struct in_addr dst; - struct route *rt; { - register struct sockaddr_in *sin; + struct sockaddr_in *sin; + struct in_ifaddr *ifa; + struct route ro; - sin = (struct sockaddr_in *)&rt->ro_dst; + bzero(&ro, sizeof(ro)); + sin = (struct sockaddr_in *)&ro.ro_dst; + sin->sin_family = AF_INET; + sin->sin_len = sizeof(*sin); + sin->sin_addr = dst; + rtalloc_ign(&ro, (RTF_PRCLONING | RTF_CLONING)); - if (rt->ro_rt == 0 || - !(rt->ro_rt->rt_flags & RTF_UP) || - dst.s_addr != sin->sin_addr.s_addr) { - 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(rt, RTF_PRCLONING); - } - if (rt->ro_rt == 0) + if (ro.ro_rt == 0) return ((struct in_ifaddr *)0); - return (ifatoia(rt->ro_rt->rt_ifa)); + + ifa = ifatoia(ro.ro_rt->rt_ifa); + RTFREE(ro.ro_rt); + return ifa; } /* @@ -1853,11 +1774,10 @@ u_char inetctlerrmap[PRC_NCMDS] = { * via a source route. */ static void -ip_forward(struct mbuf *m, struct route *ro, - int srcrt, struct sockaddr_in *next_hop) +ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop) { struct ip *ip = mtod(m, struct ip *); - struct rtentry *rt; + struct in_ifaddr *ia; int error, type = 0, code = 0; struct mbuf *mcopy; n_long dest; @@ -1867,7 +1787,6 @@ ip_forward(struct mbuf *m, struct route *ro, struct ifnet dummyifp; #endif - dest = 0; /* * Cache the destination address of the packet; this may be * changed by use of 'ipfw fwd'. @@ -1892,18 +1811,17 @@ ip_forward(struct mbuf *m, struct route *ro, #endif if (ip->ip_ttl <= IPTTLDEC) { icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, - dest, 0); + 0, 0); return; } #ifdef IPSTEALTH } #endif - if (ip_rtaddr(pkt_dst, ro) == 0) { - icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0); + if ((ia = ip_rtaddr(pkt_dst)) == 0) { + icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0); return; - } else - rt = ro->ro_rt; + } /* * Save the IP header and at most 8 bytes of the payload, @@ -1954,27 +1872,44 @@ ip_forward(struct mbuf *m, struct route *ro, * Also, don't send redirect if forwarding using a default route * or a route modified by a redirect. */ - if (rt->rt_ifp == m->m_pkthdr.rcvif && - (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 && - satosin(rt_key(rt))->sin_addr.s_addr != 0 && - ipsendredirects && !srcrt && !next_hop) { -#define RTA(rt) ((struct in_ifaddr *)(rt->rt_ifa)) - u_long src = ntohl(ip->ip_src.s_addr); + dest = 0; + if (ipsendredirects && ia->ia_ifp == m->m_pkthdr.rcvif) { + struct sockaddr_in *sin; + struct route ro; + struct rtentry *rt; - if (RTA(rt) && - (src & RTA(rt)->ia_subnetmask) == RTA(rt)->ia_subnet) { - if (rt->rt_flags & RTF_GATEWAY) - dest = satosin(rt->rt_gateway)->sin_addr.s_addr; - else - dest = pkt_dst.s_addr; - /* Router requirements says to only send host redirects */ - type = ICMP_REDIRECT; - code = ICMP_REDIRECT_HOST; + bzero(&ro, sizeof(ro)); + sin = (struct sockaddr_in *)&ro.ro_dst; + sin->sin_family = AF_INET; + sin->sin_len = sizeof(*sin); + sin->sin_addr = pkt_dst; + rtalloc_ign(&ro, (RTF_PRCLONING | RTF_CLONING)); + + rt = ro.ro_rt; + + if (rt && (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 && + satosin(rt_key(rt))->sin_addr.s_addr != 0 && + ipsendredirects && !srcrt && !next_hop) { +#define RTA(rt) ((struct in_ifaddr *)(rt->rt_ifa)) + u_long src = ntohl(ip->ip_src.s_addr); + + if (RTA(rt) && + (src & RTA(rt)->ia_subnetmask) == RTA(rt)->ia_subnet) { + if (rt->rt_flags & RTF_GATEWAY) + dest = satosin(rt->rt_gateway)->sin_addr.s_addr; + else + dest = pkt_dst.s_addr; + /* Router requirements says to only send host redirects */ + type = ICMP_REDIRECT; + code = ICMP_REDIRECT_HOST; #ifdef DIAGNOSTIC - if (ipprintfs) - printf("redirect (%d) to %lx\n", code, (u_long)dest); + if (ipprintfs) + printf("redirect (%d) to %lx\n", code, (u_long)dest); #endif + } } + if (rt) + RTFREE(rt); } { @@ -1989,13 +1924,8 @@ ip_forward(struct mbuf *m, struct route *ro, tag.mh_next = m; m = (struct mbuf *)&tag; } - error = ip_output(m, (struct mbuf *)0, ro, IP_FORWARDING, 0, NULL); + error = ip_output(m, (struct mbuf *)0, NULL, IP_FORWARDING, 0, NULL); } - /* - * Update the ip forwarding cache with the route we used. - * We may want to do this more selectively; not sure. - */ - RTCACHE_UPDATE(ro); if (error) ipstat.ips_cantforward++; else { @@ -2030,77 +1960,31 @@ ip_forward(struct mbuf *m, struct route *ro, case EMSGSIZE: type = ICMP_UNREACH; code = ICMP_UNREACH_NEEDFRAG; -#ifdef IPSEC +#if defined(IPSEC) || defined(FAST_IPSEC) /* * If the packet is routed over IPsec tunnel, tell the * originator the tunnel MTU. * tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz * XXX quickhack!!! */ - if (ro->ro_rt) { + { struct secpolicy *sp = NULL; int ipsecerror; int ipsechdr; + struct route *ro; +#ifdef IPSEC sp = ipsec4_getpolicybyaddr(mcopy, IPSEC_DIR_OUTBOUND, - IP_FORWARDING, - &ipsecerror); - - if (sp == NULL) - destifp = ro->ro_rt->rt_ifp; - else { - /* count IPsec header size */ - ipsechdr = ipsec4_hdrsiz(mcopy, - IPSEC_DIR_OUTBOUND, - NULL); - - /* - * find the correct route for outer IPv4 - * header, compute tunnel MTU. - * - * XXX BUG ALERT - * The "dummyifp" code relies upon the fact - * that icmp_error() touches only ifp->if_mtu. - */ - /*XXX*/ - destifp = NULL; - if (sp->req != NULL - && sp->req->sav != NULL - && sp->req->sav->sah != NULL) { - struct route *saro; - saro = &sp->req->sav->sah->sa_route; - if (saro->ro_rt && saro->ro_rt->rt_ifp) { - dummyifp.if_mtu = - saro->ro_rt->rt_ifp->if_mtu; - dummyifp.if_mtu -= ipsechdr; - destifp = &dummyifp; - } - } - - key_freesp(sp); - } - } -#elif FAST_IPSEC - /* - * If the packet is routed over IPsec tunnel, tell the - * originator the tunnel MTU. - * tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz - * XXX quickhack!!! - */ - if (ro->ro_rt) { - struct secpolicy *sp = NULL; - int ipsecerror; - int ipsechdr; - + IP_FORWARDING, + &ipsecerror); +#else /* FAST_IPSEC */ sp = ipsec_getpolicybyaddr(mcopy, IPSEC_DIR_OUTBOUND, - IP_FORWARDING, - &ipsecerror); - - if (sp == NULL) - destifp = ro->ro_rt->rt_ifp; - else { + IP_FORWARDING, + &ipsecerror); +#endif + if (sp != NULL) { /* count IPsec header size */ ipsechdr = ipsec4_hdrsiz(mcopy, IPSEC_DIR_OUTBOUND, @@ -2119,23 +2003,28 @@ ip_forward(struct mbuf *m, struct route *ro, if (sp->req != NULL && sp->req->sav != NULL && sp->req->sav->sah != NULL) { - struct route *saro; - saro = &sp->req->sav->sah->sa_route; - if (saro->ro_rt && saro->ro_rt->rt_ifp) { + ro = &sp->req->sav->sah->sa_route; + if (ro->ro_rt && ro->ro_rt->rt_ifp) { dummyifp.if_mtu = - saro->ro_rt->rt_ifp->if_mtu; + ro->ro_rt->rt_ifp->if_mtu; dummyifp.if_mtu -= ipsechdr; destifp = &dummyifp; } } +#ifdef IPSEC + key_freesp(sp); +#else /* FAST_IPSEC */ KEY_FREESP(&sp); - } +#endif + ipstat.ips_cantfrag++; + break; + } else +#endif /*IPSEC || FAST_IPSEC*/ + destifp = ia->ia_ifp; +#if defined(IPSEC) || defined(FAST_IPSEC) } -#else /* !IPSEC && !FAST_IPSEC */ - if (ro->ro_rt) - destifp = ro->ro_rt->rt_ifp; -#endif /*IPSEC*/ +#endif /*IPSEC || FAST_IPSEC*/ ipstat.ips_cantfrag++; break; diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index fb4bff745369..64d4a7009f17 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -142,13 +142,12 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, struct in_ifaddr *ia = NULL; int isbroadcast, sw_csum; struct in_addr pkt_dst; -#ifdef IPSEC struct route iproute; +#ifdef IPSEC struct socket *so; struct secpolicy *sp = NULL; #endif #ifdef FAST_IPSEC - struct route iproute; struct m_tag *mtag; struct secpolicy *sp = NULL; struct tdb_ident *tdbi; @@ -202,10 +201,12 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, #endif /*IPSEC*/ M_ASSERTPKTHDR(m); -#ifndef FAST_IPSEC - KASSERT(ro != NULL, ("ip_output: no route, proto %d", - mtod(m, struct ip *)->ip_p)); -#endif + + if (ro == NULL) { + ro = &iproute; + bzero(ro, sizeof (*ro)); + } + if (inp != NULL) INP_LOCK_ASSERT(inp); @@ -256,12 +257,6 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, hlen = ip->ip_hl << 2; } -#ifdef FAST_IPSEC - if (ro == NULL) { - ro = &iproute; - bzero(ro, sizeof (*ro)); - } -#endif /* FAST_IPSEC */ dst = (struct sockaddr_in *)&ro->ro_dst; /* * If there is a cached route, @@ -1089,11 +1084,11 @@ pass: ipstat.ips_fragmented++; done: -#ifdef IPSEC if (ro == &iproute && ro->ro_rt) { RTFREE(ro->ro_rt); ro->ro_rt = NULL; } +#ifdef IPSEC if (sp != NULL) { KEYDEBUG(KEYDEBUG_IPSEC_STAMP, printf("DP ip_output call free SP:%p\n", sp)); @@ -1101,10 +1096,6 @@ done: } #endif #ifdef FAST_IPSEC - if (ro == &iproute && ro->ro_rt) { - RTFREE(ro->ro_rt); - ro->ro_rt = NULL; - } if (sp != NULL) KEY_FREESP(&sp); #endif diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 1b9d6c5aa583..964afd0ebfdf 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -162,7 +162,6 @@ int ip_ctloutput(struct socket *, struct sockopt *sopt); void ip_drain(void); int ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu, u_long if_hwassist_flags, int sw_csum); -void ip_forward_cacheinval(void); void ip_freemoptions(struct ip_moptions *); void ip_init(void); extern int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *, @@ -171,7 +170,7 @@ int ip_output(struct mbuf *, struct mbuf *, struct route *, int, struct ip_moptions *, struct inpcb *); struct in_ifaddr * - ip_rtaddr(struct in_addr, struct route *); + ip_rtaddr(struct in_addr); void ip_savecontrol(struct inpcb *, struct mbuf **, struct ip *, struct mbuf *); void ip_slowtimo(void);