On 13/11/14(Thu) 15:42, Martin Pieuchot wrote:
> In order to do *only one* route lookup without using a global variable
> (yes, I'm looking at you netinet6) and without doing too much spaghetti,
> here's a refactoring of ip_input().
> 
> It basically merges in_ouraddr() into ip_input(), but some operations
> are shuffled, when possible, to reduces differences with the IPv6
> version.
> 
> It also increments rt_use counters for the local routes, (say yeah!).
> 
> Comment, bikeshed, ok?

I'm still looking for reviews, nobody?

> 
> Index: netinet/ip_input.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/netinet/ip_input.c,v
> retrieving revision 1.240
> diff -u -p -r1.240 ip_input.c
> --- netinet/ip_input.c        4 Nov 2014 15:24:40 -0000       1.240
> +++ netinet/ip_input.c        5 Nov 2014 13:52:25 -0000
> @@ -123,7 +123,6 @@ struct ipstat ipstat;
>  
>  void ip_ours(struct mbuf *);
>  int  ip_dooptions(struct mbuf *, struct ifnet *);
> -int  in_ouraddr(struct mbuf *, struct ifnet *, struct in_addr);
>  void ip_forward(struct mbuf *, struct ifnet *, int);
>  
>  /*
> @@ -222,6 +221,8 @@ ipintr(void)
>  void
>  ipv4_input(struct mbuf *m)
>  {
> +     struct sockaddr_in sin;
> +     struct rtentry *rt;
>       struct ifnet *ifp;
>       struct ip *ip;
>       int hlen, len;
> @@ -341,11 +342,25 @@ ipv4_input(struct mbuf *m)
>               return;
>       }
>  
> -     if (in_ouraddr(m, ifp, ip->ip_dst)) {
> +     if (ip->ip_dst.s_addr == INADDR_BROADCAST ||
> +         ip->ip_dst.s_addr == INADDR_ANY) {
> +             ip_ours(m);
> +             return;
> +     }
> +
> +#if NPF > 0
> +     /* No need for a route lookup if we already know it's for us. */
> +     if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED ||
> +         (m->m_pkthdr.pf.statekey && m->m_pkthdr.pf.statekey->inp)) {
>               ip_ours(m);
>               return;
>       }
>  
> +     /* If we have linked state keys it is certainly forwarded. */
> +     if (m->m_pkthdr.pf.statekey && m->m_pkthdr.pf.statekey->reverse)
> +             goto forward;
> +#endif
> +
>       if (IN_MULTICAST(ip->ip_dst.s_addr)) {
>               struct in_multi *inm;
>  #ifdef MROUTING
> @@ -401,12 +416,79 @@ ipv4_input(struct mbuf *m)
>               return;
>       }
>  
> -     if (ip->ip_dst.s_addr == INADDR_BROADCAST ||
> -         ip->ip_dst.s_addr == INADDR_ANY) {
> -             ip_ours(m);
> -             return;
> +     memset(&sin, 0, sizeof(sin));
> +     sin.sin_len = sizeof(sin);
> +     sin.sin_family = AF_INET;
> +     sin.sin_addr = ip->ip_dst;
> +
> +     rt = rtalloc(sintosa(&sin), 0, m->m_pkthdr.ph_rtableid);
> +     if (rt != NULL) {
> +             /*
> +              * We consider a packet as local if its destination
> +              * matches a local route and the associated interface
> +              * is up.
> +              */
> +             if (ISSET(rt->rt_flags, RTF_LOCAL)) {
> +                     /*
> +                      * XXX Since local routes' rt_ifp points to lo0
> +                      * we cannot rely on the rtentry flags.
> +                      */
> +                     if (ISSET(rt->rt_ifa->ifa_ifp->if_flags, IFF_UP)) {
> +                             rt->rt_use++;
> +                             rtfree(rt);
> +                             ip_ours(m);
> +                             return;
> +                     }
> +             }
> +
> +             /*
> +              * This matches a broadcast address on one of our interfaces.
> +              * If directedbcast is enabled we only consider it local if it
> +              * is received on the interface with that address.
> +              */
> +             if (ISSET(rt->rt_flags, RTF_BROADCAST) &&
> +                 ISSET(rt->rt_flags, RTF_UP) &&
> +                 (!ip_directedbcast || rt->rt_ifp == ifp)) {
> +                     rt->rt_use++;
> +                     rtfree(rt);
> +
> +                     /* Make sure M_BCAST is set */
> +                     m->m_flags |= M_BCAST;
> +                     ip_ours(m);
> +                     return;
> +             }
> +
> +             rtfree(rt);
> +     }
> +
> +     /*
> +      * No local address or broadcast address found, so check for
> +      * ancient classful broadcast addresses.
> +      * It must have been broadcast on the link layer, and for an
> +      * address on the interface it was received on.
> +      */
> +     if (ISSET(m->m_flags, M_BCAST) &&
> +         IN_CLASSFULBROADCAST(ip->ip_dst.s_addr, ip->ip_dst.s_addr)) {
> +             struct ifaddr *ifa;
> +
> +             /*
> +              * The check in the loop assumes you only rx a packet
> +              * on an UP interface, and that M_BCAST will only be
> +              * set on a BROADCAST interface.
> +              */
> +             TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
> +                     if (ifa->ifa_addr->sa_family != AF_INET)
> +                             continue;
> +
> +                     if (IN_CLASSFULBROADCAST(ip->ip_dst.s_addr,
> +                         ifatoia(ifa)->ia_addr.sin_addr.s_addr)) {
> +                             ip_ours(m);
> +                             return;
> +                     }
> +             }
>       }
>  
> +forward:
>  #if NCARP > 0
>       if (ifp->if_type == IFT_CARP && ip->ip_p == IPPROTO_ICMP &&
>           carp_lsdrop(m, AF_INET, &ip->ip_src.s_addr, &ip->ip_dst.s_addr))
> @@ -636,89 +718,6 @@ found:
>       return;
>  bad:
>       m_freem(m);
> -}
> -
> -int
> -in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct in_addr ina)
> -{
> -     struct in_ifaddr        *ia = NULL;
> -     struct rtentry          *rt;
> -     struct sockaddr_in       sin;
> -#if NPF > 0
> -     struct pf_state_key     *key;
> -
> -     if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED)
> -             return (1);
> -
> -     key = m->m_pkthdr.pf.statekey;
> -     if (key != NULL) {
> -             if (key->inp != NULL)
> -                     return (1);
> -
> -             /* If we have linked state keys it is certainly forwarded. */
> -             if (key->reverse != NULL)
> -                     return (0);
> -     }
> -#endif
> -
> -     memset(&sin, 0, sizeof(sin));
> -     sin.sin_len = sizeof(sin);
> -     sin.sin_family = AF_INET;
> -     sin.sin_addr = ina;
> -     rt = rtalloc(sintosa(&sin), 0, m->m_pkthdr.ph_rtableid);
> -     if (rt != NULL) {
> -             if (rt->rt_flags & (RTF_LOCAL|RTF_BROADCAST))
> -                     ia = ifatoia(rt->rt_ifa);
> -             rtfree(rt);
> -     }
> -
> -     if (ia == NULL) {
> -             struct ifaddr *ifa;
> -
> -             /*
> -              * No local address or broadcast address found, so check for
> -              * ancient classful broadcast addresses.
> -              * It must have been broadcast on the link layer, and for an
> -              * address on the interface it was received on.
> -              */
> -             if (!ISSET(m->m_flags, M_BCAST) ||
> -                 !IN_CLASSFULBROADCAST(ina.s_addr, ina.s_addr))
> -                     return (0);
> -
> -             if (ifp->if_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid))
> -                     return (0);
> -             /*
> -              * The check in the loop assumes you only rx a packet on an UP
> -              * interface, and that M_BCAST will only be set on a BROADCAST
> -              * interface.
> -              */
> -             TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
> -                     if (ifa->ifa_addr->sa_family != AF_INET)
> -                             continue;
> -
> -                     if (IN_CLASSFULBROADCAST(ina.s_addr,
> -                         ifatoia(ifa)->ia_addr.sin_addr.s_addr))
> -                             return (1);
> -             }
> -
> -             return (0);
> -     }
> -
> -     if (ina.s_addr != ia->ia_addr.sin_addr.s_addr) {
> -             /*
> -              * This matches a broadcast address on one of our interfaces.
> -              * If directedbcast is enabled we only consider it local if it
> -              * is received on the interface with that address.
> -              */
> -             if (ip_directedbcast && ia->ia_ifp != ifp)
> -                     return (0);
> -
> -             /* Make sure M_BCAST is set */
> -             if (m)
> -                     m->m_flags |= M_BCAST;
> -     }
> -
> -     return (ISSET(ia->ia_ifp->if_flags, IFF_UP));
>  }
>  
>  struct in_ifaddr *
> 

Reply via email to