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 *);
> 

Reply via email to