Author: glebius
Date: Mon Jul 23 09:19:14 2012
New Revision: 238713
URL: http://svn.freebsd.org/changeset/base/238713

Log:
  Merge from head r238572, r238573:
    ------------------------------------------------------------------------
    r238572 | glebius | 2012-07-18 12:41:00 +0400 (ср, 18 июл 2012) | 3 lines
  
    When traversing global in_ifaddr list in the IFP_TO_IA() macro, we need
    to obtain IN_IFADDR_RLOCK().
  
    ------------------------------------------------------------------------
    r238573 | glebius | 2012-07-18 12:58:30 +0400 (ср, 18 июл 2012) | 5 lines
  
    Plug a reference leak: before doing 'goto again' we need to unref
    ia->ia_ifa if there is any.
  
    Submitted by:   Andrey Zonov <andrey zonov.org>
  
  Approved by:  re (kib)

Modified:
  stable/9/sys/netinet/in_var.h
  stable/9/sys/netinet/ip_output.c
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/netinet/in_var.h
==============================================================================
--- stable/9/sys/netinet/in_var.h       Mon Jul 23 04:48:58 2012        
(r238712)
+++ stable/9/sys/netinet/in_var.h       Mon Jul 23 09:19:14 2012        
(r238713)
@@ -159,14 +159,16 @@ do { \
 #define IFP_TO_IA(ifp, ia)                                             \
        /* struct ifnet *ifp; */                                        \
        /* struct in_ifaddr *ia; */                                     \
-{                                                                      \
+do {                                                                   \
+       IN_IFADDR_RLOCK();                                              \
        for ((ia) = TAILQ_FIRST(&V_in_ifaddrhead);                      \
            (ia) != NULL && (ia)->ia_ifp != (ifp);                      \
            (ia) = TAILQ_NEXT((ia), ia_link))                           \
                continue;                                               \
        if ((ia) != NULL)                                               \
                ifa_ref(&(ia)->ia_ifa);                                 \
-}
+       IN_IFADDR_RUNLOCK();                                            \
+} while (0)
 #endif
 
 /*

Modified: stable/9/sys/netinet/ip_output.c
==============================================================================
--- stable/9/sys/netinet/ip_output.c    Mon Jul 23 04:48:58 2012        
(r238712)
+++ stable/9/sys/netinet/ip_output.c    Mon Jul 23 09:19:14 2012        
(r238713)
@@ -121,7 +121,7 @@ ip_output(struct mbuf *m, struct mbuf *o
        int error = 0;
        int nortfree = 0;
        struct sockaddr_in *dst;
-       struct in_ifaddr *ia = NULL;
+       struct in_ifaddr *ia;
        int isbroadcast, sw_csum;
        struct route iproute;
        struct rtentry *rte;    /* cache for ro->ro_rt */
@@ -196,6 +196,7 @@ ip_output(struct mbuf *m, struct mbuf *o
 
        dst = (struct sockaddr_in *)&ro->ro_dst;
 again:
+       ia = NULL;
        /*
         * If there is a cached route,
         * check that it is to the same destination
@@ -532,8 +533,11 @@ sendit:
 #endif
                        error = netisr_queue(NETISR_IP, m);
                        goto done;
-               } else
+               } else {
+                       if (ia != NULL)
+                               ifa_free(&ia->ia_ifa);
                        goto again;     /* Redo the routing table lookup. */
+               }
        }
 
 #ifdef IPFIREWALL_FORWARD
@@ -563,6 +567,8 @@ sendit:
                bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in));
                m->m_flags |= M_SKIP_FIREWALL;
                m_tag_delete(m, fwd_tag);
+               if (ia != NULL)
+                       ifa_free(&ia->ia_ifa);
                goto again;
        }
 #endif /* IPFIREWALL_FORWARD */
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to