Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/netinet fix problem we can't drop membership on !IFF_UP ...



details:   https://anonhg.NetBSD.org/src/rev/505764cb026d
branches:  trunk
changeset: 550722:505764cb026d
user:      itojun <itojun%NetBSD.org@localhost>
date:      Mon Aug 18 22:23:22 2003 +0000

description:
fix problem we can't drop membership on !IFF_UP interface.
reported by Shiva Shenoy

while we're here, fix another problem when the same interface address is
assigned to !IFF_MULTICAST and IFF_MULTICAST interface.  if ip_multicast_if()
returns the first one, join/leave will fail, which is not an desired effect.

diffstat:

 sys/netinet/ip_output.c |  152 +++++++++++++++++++++++++++--------------------
 1 files changed, 88 insertions(+), 64 deletions(-)

diffs (224 lines):

diff -r 9c0008bfaa1a -r 505764cb026d sys/netinet/ip_output.c
--- a/sys/netinet/ip_output.c   Mon Aug 18 22:10:33 2003 +0000
+++ b/sys/netinet/ip_output.c   Mon Aug 18 22:23:22 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_output.c,v 1.109 2003/08/15 03:42:03 jonathan Exp $ */
+/*     $NetBSD: ip_output.c,v 1.110 2003/08/18 22:23:22 itojun Exp $   */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -98,7 +98,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.109 2003/08/15 03:42:03 jonathan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.110 2003/08/18 22:23:22 itojun Exp $");
 
 #include "opt_pfil_hooks.h"
 #include "opt_ipsec.h"
@@ -167,11 +167,11 @@
        va_dcl
 #endif
 {
-       struct ip *ip, *mhip;
+       struct ip *ip;
        struct ifnet *ifp;
        struct mbuf *m = m0;
        int hlen = sizeof (struct ip);
-       int len, off, error = 0;
+       int len, error = 0;
        struct route iproute;
        struct sockaddr_in *dst;
        struct in_ifaddr *ia;
@@ -461,7 +461,8 @@
 #ifdef IPSEC
        /* get SP for this packet */
        if (so == NULL)
-               sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, flags, &error);
+               sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND,
+                   flags, &error);
        else
                sp = ipsec4_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error);
 
@@ -584,7 +585,6 @@
                        ifp = ro->ro_rt->rt_ifp;
        }
     }
-
 skip_ipsec:
 #endif /*IPSEC*/
 #ifdef FAST_IPSEC
@@ -794,17 +794,87 @@
                ipstat.ips_cantfrag++;
                goto bad;
        }
-       len = (mtu - hlen) &~ 7;
-       if (len < 8) {
-               error = EMSGSIZE;
+
+       error = ip_fragment(m, ifp, mtu);
+       if (error == EMSGSIZE)
                goto bad;
+
+       for (m = m0; m; m = m0) {
+               m0 = m->m_nextpkt;
+               m->m_nextpkt = 0;
+               if (error == 0) {
+#if IFA_STATS
+                       /*
+                        * search for the source address structure to
+                        * maintain output statistics.
+                        */
+                       INADDR_TO_IA(ip->ip_src, ia);
+                       if (ia) {
+                               ia->ia_ifa.ifa_data.ifad_outbytes +=
+                                   ntohs(ip->ip_len);
+                       }
+#endif
+#ifdef IPSEC
+                       /* clean ipsec history once it goes out of the node */
+                       ipsec_delaux(m);
+#endif
+                       KASSERT((m->m_pkthdr.csum_flags &
+                           (M_CSUM_UDPv4 | M_CSUM_TCPv4)) == 0);
+                       error = (*ifp->if_output)(ifp, m, sintosa(dst),
+                           ro->ro_rt);
+               } else
+                       m_freem(m);
+       }
+
+       if (error == 0)
+               ipstat.ips_fragmented++;
+done:
+       if (ro == &iproute && (flags & IP_ROUTETOIF) == 0 && ro->ro_rt) {
+               RTFREE(ro->ro_rt);
+               ro->ro_rt = 0;
        }
 
-    {
-       int mhlen, firstlen = len;
-       struct mbuf **mnext = &m->m_nextpkt;
+#ifdef IPSEC
+       if (sp != NULL) {
+               KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
+                       printf("DP ip_output call free SP:%p\n", sp));
+               key_freesp(sp);
+       }
+#endif /* IPSEC */
+#ifdef FAST_IPSEC
+       if (sp != NULL)
+               KEY_FREESP(&sp);
+#endif /* FAST_IPSEC */
+
+       return (error);
+bad:
+       m_freem(m);
+       goto done;
+}
+
+int
+ip_fragment(struct mbuf *m, struct ifnet *ifp, u_long mtu)
+{
+       struct ip *ip, *mhip;
+       struct mbuf *m0;
+       int len, hlen, off;
+       int mhlen, firstlen;
+       struct mbuf **mnext;
+       int sw_csum;
        int fragments = 0;
        int s;
+       int error = 0;
+
+       ip = mtod(m, struct ip *);
+       hlen = ip->ip_hl << 2;
+       sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_csum_flags_tx;
+
+       len = (mtu - hlen) &~ 7;
+       if (len < 8)
+               return (EMSGSIZE);
+
+       firstlen = len;
+       mnext = &m->m_nextpkt;
 
        /*
         * Loop through length of segment after first fragment,
@@ -884,58 +954,7 @@
        if (ifp->if_snd.ifq_maxlen - ifp->if_snd.ifq_len < fragments)
                error = ENOBUFS;
        splx(s);
-       for (m = m0; m; m = m0) {
-               m0 = m->m_nextpkt;
-               m->m_nextpkt = 0;
-               if (error == 0) {
-#if IFA_STATS
-                       /*
-                        * search for the source address structure to
-                        * maintain output statistics.
-                        */
-                       INADDR_TO_IA(ip->ip_src, ia);
-                       if (ia) {
-                               ia->ia_ifa.ifa_data.ifad_outbytes +=
-                                   ntohs(ip->ip_len);
-                       }
-#endif
-#ifdef IPSEC
-                       /* clean ipsec history once it goes out of the node */
-                       ipsec_delaux(m);
-#endif
-                       KASSERT((m->m_pkthdr.csum_flags &
-                           (M_CSUM_UDPv4 | M_CSUM_TCPv4)) == 0);
-                       error = (*ifp->if_output)(ifp, m, sintosa(dst),
-                           ro->ro_rt);
-               } else
-                       m_freem(m);
-       }
-
-       if (error == 0)
-               ipstat.ips_fragmented++;
-    }
-done:
-       if (ro == &iproute && (flags & IP_ROUTETOIF) == 0 && ro->ro_rt) {
-               RTFREE(ro->ro_rt);
-               ro->ro_rt = 0;
-       }
-
-#ifdef IPSEC
-       if (sp != NULL) {
-               KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
-                       printf("DP ip_output call free SP:%p\n", sp));
-               key_freesp(sp);
-       }
-#endif /* IPSEC */
-#ifdef FAST_IPSEC
-       if (sp != NULL)
-               KEY_FREESP(&sp);
-#endif /* FAST_IPSEC */
-
        return (error);
-bad:
-       m_freem(m);
-       goto done;
 }
 
 /*
@@ -1446,6 +1465,7 @@
 {
        int ifindex;
        struct ifnet *ifp;
+       struct in_ifaddr *ia;
 
        if (ifindexp)
                *ifindexp = 0;
@@ -1457,7 +1477,11 @@
                if (ifindexp)
                        *ifindexp = ifindex;
        } else {
-               INADDR_TO_IFP(*a, ifp);
+               LIST_FOREACH(ia, &IN_IFADDR_HASH(a->s_addr), ia_hash) {
+                       if (in_hosteq(ia->ia_addr.sin_addr, *a) &&
+                           (ia->ia_ifp->if_flags & IFF_MULTICAST) != 0)
+                               break;
+               }
        }
        return ifp;
 }



Home | Main Index | Thread Index | Old Index