On Mon, Apr 11, 2016 at 15:17 +0200, Martin Pieuchot wrote:
> ``ipforward_rt'' is going away but rather than sending a big diff,
> here's the first step.
>
> This diff replaces in_rtaddr() by rtalloc(9). Note that since the code
> here is interested in rt_ifa it has to call rtisvalid(9) to prevent a
> NULL-dereference in case of a stale ``ifa''.
>
> For the same reason rtfree(9) has to be called *after* the pointer has
> been dereferenced. Because the reference on ``rt'' acts as a proxy for
> ``ifa''.
>
> ok?
>
Looks good to me. FWIW, OK mikeb
> Index: netinet/ip_input.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_input.c,v
> retrieving revision 1.269
> diff -u -p -r1.269 ip_input.c
> --- netinet/ip_input.c 29 Mar 2016 10:34:42 -0000 1.269
> +++ netinet/ip_input.c 11 Apr 2016 13:10:51 -0000
> @@ -1013,6 +1013,8 @@ int
> ip_dooptions(struct mbuf *m, struct ifnet *ifp)
> {
> struct ip *ip = mtod(m, struct ip *);
> + unsigned int rtableid = m->m_pkthdr.ph_rtableid;
> + struct rtentry *rt;
> struct sockaddr_in ipaddr;
> u_char *cp;
> struct ip_timestamp ipt;
> @@ -1108,19 +1110,31 @@ ip_dooptions(struct mbuf *m, struct ifne
> m->m_pkthdr.ph_rtableid))) == NULL)
> ia = ifatoia(ifa_ifwithnet(sintosa(&ipaddr),
> m->m_pkthdr.ph_rtableid));
> - } else
> + if (ia == NULL) {
> + type = ICMP_UNREACH;
> + code = ICMP_UNREACH_SRCFAIL;
> + goto bad;
> + }
> + memcpy(cp + off, &ia->ia_addr.sin_addr,
> + sizeof(struct in_addr));
> + cp[IPOPT_OFFSET] += sizeof(struct in_addr);
> + } else {
> /* keep packet in the virtual instance */
> - ia = ip_rtaddr(ipaddr.sin_addr,
> - m->m_pkthdr.ph_rtableid);
> - if (ia == NULL) {
> - type = ICMP_UNREACH;
> - code = ICMP_UNREACH_SRCFAIL;
> - goto bad;
> + rt = rtalloc(sintosa(&ipaddr), RT_RESOLVE,
> + rtableid);
> + if (!rtisvalid(rt)) {
> + type = ICMP_UNREACH;
> + code = ICMP_UNREACH_SRCFAIL;
> + rtfree(rt);
> + goto bad;
> + }
> + ia = ifatoia(rt->rt_ifa);
> + memcpy(cp + off, &ia->ia_addr.sin_addr,
> + sizeof(struct in_addr));
> + rtfree(rt);
> + cp[IPOPT_OFFSET] += sizeof(struct in_addr);
> }
> ip->ip_dst = ipaddr.sin_addr;
> - memcpy(cp + off, &ia->ia_addr.sin_addr,
> - sizeof(struct in_addr));
> - cp[IPOPT_OFFSET] += sizeof(struct in_addr);
> /*
> * Let ip_intr's mcast routing check handle mcast pkts
> */
> @@ -1152,16 +1166,17 @@ ip_dooptions(struct mbuf *m, struct ifne
> * use the incoming interface (should be same).
> * Again keep the packet inside the virtual instance.
> */
> - if ((ia = ifatoia(ifa_ifwithaddr(sintosa(&ipaddr),
> - m->m_pkthdr.ph_rtableid))) == NULL &&
> - (ia = ip_rtaddr(ipaddr.sin_addr,
> - m->m_pkthdr.ph_rtableid)) == NULL) {
> + rt = rtalloc(sintosa(&ipaddr), RT_RESOLVE, rtableid);
> + if (!rtisvalid(rt)) {
> type = ICMP_UNREACH;
> code = ICMP_UNREACH_HOST;
> + rtfree(rt);
> goto bad;
> }
> + ia = ifatoia(rt->rt_ifa);
> memcpy(cp + off, &ia->ia_addr.sin_addr,
> sizeof(struct in_addr));
> + rtfree(rt);
> cp[IPOPT_OFFSET] += sizeof(struct in_addr);
> break;
>
> @@ -1234,34 +1249,6 @@ bad:
> icmp_error(m, type, code, 0, 0);
> ipstat.ips_badoptions++;
> return (1);
> -}
> -
> -/*
> - * Given address of next destination (final or next hop),
> - * return internet address info of interface to be used to get there.
> - */
> -struct in_ifaddr *
> -ip_rtaddr(struct in_addr dst, u_int rtableid)
> -{
> - struct sockaddr_in *sin;
> -
> - sin = satosin(&ipforward_rt.ro_dst);
> -
> - if (ipforward_rt.ro_rt == 0 || dst.s_addr != sin->sin_addr.s_addr) {
> - if (ipforward_rt.ro_rt) {
> - rtfree(ipforward_rt.ro_rt);
> - ipforward_rt.ro_rt = NULL;
> - }
> - sin->sin_family = AF_INET;
> - sin->sin_len = sizeof(*sin);
> - sin->sin_addr = dst;
> -
> - ipforward_rt.ro_rt = rtalloc(&ipforward_rt.ro_dst,
> - RT_RESOLVE, rtableid);
> - }
> - if (ipforward_rt.ro_rt == 0)
> - return (NULL);
> - return (ifatoia(ipforward_rt.ro_rt->rt_ifa));
> }
>
> /*
> Index: netinet/ip_var.h
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_var.h,v
> retrieving revision 1.61
> diff -u -p -r1.61 ip_var.h
> --- netinet/ip_var.h 3 Dec 2015 21:11:53 -0000 1.61
> +++ netinet/ip_var.h 11 Apr 2016 13:10:51 -0000
> @@ -189,8 +189,6 @@ int ip_output(struct mbuf *, struct mbu
> int ip_pcbopts(struct mbuf **, struct mbuf *);
> struct mbuf *
> ip_reass(struct ipqent *, struct ipq *);
> -struct in_ifaddr *
> - ip_rtaddr(struct in_addr, u_int);
> u_int16_t
> ip_randomid(void);
> void ip_send(struct mbuf *);
>