Source-Changes-HG archive

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

[src/trunk]: src/sys avoid calling in6_control(SIOCDIFADDR_IN6) from interrup...



details:   https://anonhg.NetBSD.org/src/rev/f88a15039902
branches:  trunk
changeset: 481737:f88a15039902
user:      itojun <itojun%NetBSD.org@localhost>
date:      Fri Feb 04 14:34:22 2000 +0000

description:
avoid calling in6_control(SIOCDIFADDR_IN6) from interrupt context.
it is not supposed to work.
logging fix: add "\n" to some of log() in in6_prefix.c.

improve in6_ifdetach().  now almost all structure depend on ifnet
will be cleared up.
possible loose ends:
- cached route_in6 in static varaiables needs to be cleared as well
- there are ifaddr manipulation without reference counting,
  which should be fixed
we still see panics after card removal, though...  not sure what is left.

(sync with kame)

diffstat:

 sys/netinet/tcp_usrreq.c    |   3 +-
 sys/netinet6/in6_ifattach.c |  10 +++-
 sys/netinet6/in6_prefix.c   |  76 +++++++++++++++++-------------------
 sys/netinet6/in6_prefix.h   |   5 +-
 sys/netinet6/in6_var.h      |   3 +-
 sys/netinet6/nd6.c          |  94 ++++++++++++++++++++++++++++++++++++++++++++-
 sys/netinet6/nd6.h          |   3 +-
 7 files changed, 145 insertions(+), 49 deletions(-)

diffs (truncated from 431 to 300 lines):

diff -r 6ae0cfafa23f -r f88a15039902 sys/netinet/tcp_usrreq.c
--- a/sys/netinet/tcp_usrreq.c  Fri Feb 04 14:21:33 2000 +0000
+++ b/sys/netinet/tcp_usrreq.c  Fri Feb 04 14:34:22 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tcp_usrreq.c,v 1.46 2000/02/02 23:28:09 thorpej Exp $  */
+/*     $NetBSD: tcp_usrreq.c,v 1.47 2000/02/04 14:34:22 itojun Exp $   */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -204,6 +204,7 @@
                in_purgeif((struct ifnet *)control);
                in_pcbpurgeif(&tcbtable, (struct ifnet *)control);
 #ifdef INET6
+               in6_purgeif((struct ifnet *)control);
                in6_pcbpurgeif(&tcb6, (struct ifnet *)control);
 #endif
                return (0);
diff -r 6ae0cfafa23f -r f88a15039902 sys/netinet6/in6_ifattach.c
--- a/sys/netinet6/in6_ifattach.c       Fri Feb 04 14:21:33 2000 +0000
+++ b/sys/netinet6/in6_ifattach.c       Fri Feb 04 14:34:22 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in6_ifattach.c,v 1.17 2000/02/02 16:58:11 itojun Exp $ */
+/*     $NetBSD: in6_ifattach.c,v 1.18 2000/02/04 14:34:25 itojun Exp $ */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -628,6 +628,12 @@
        short rtflags;
        struct sockaddr_in6 sin6;
 
+       /* nuke prefix list.  this may try to remove some of ifaddrs as well */
+       in6_purgeprefix(ifp);
+
+       /* remove neighbor management table */
+       nd6_purge(ifp);
+
        for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
        {
                if (ifa->ifa_addr->sa_family != AF_INET6
@@ -673,7 +679,7 @@
 
        /* cleanup multicast address kludge table, if there is any */
        in6_purgemkludge(ifp);
-  
+
        /* remove route to link-local allnodes multicast (ff02::1) */
        bzero(&sin6, sizeof(sin6));
        sin6.sin6_len = sizeof(struct sockaddr_in6);
diff -r 6ae0cfafa23f -r f88a15039902 sys/netinet6/in6_prefix.c
--- a/sys/netinet6/in6_prefix.c Fri Feb 04 14:21:33 2000 +0000
+++ b/sys/netinet6/in6_prefix.c Fri Feb 04 14:34:22 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in6_prefix.c,v 1.6 2000/02/03 12:13:50 itojun Exp $    */
+/*     $NetBSD: in6_prefix.c,v 1.7 2000/02/04 14:34:25 itojun Exp $    */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -205,7 +205,7 @@
        }
        if (ifpr != NULL)
                log(LOG_ERR,  "in6_prefix.c: search_matched_prefix: addr %s"
-                   "has no pointer to prefix %s", ip6_sprintf(IFA_IN6(ifa)),
+                   "has no pointer to prefix %s\n", ip6_sprintf(IFA_IN6(ifa)),
                    ip6_sprintf(IFPR_IN6(ifpr)));
        return ifpr2rp(ifpr);
 }
@@ -263,7 +263,7 @@
                } else
                        log(LOG_WARNING, "in6_prefix.c: mark_matched_prefixes:"
                            "no back pointer to ifprefix for %s. "
-                           "ND autoconfigured addr?",
+                           "ND autoconfigured addr?\n",
                            ip6_sprintf(IFA_IN6(ifa)));
        }
        return matched;
@@ -457,7 +457,7 @@
                else if (rap->ra_addr != ia) {
                        /* There may be some inconsistencies between addrs. */
                        log(LOG_ERR, "ip6_prefix.c: addr %s/%d matched prefix"
-                           "has already another ia %p(%s) on its ifid list",
+                           "has already another ia %p(%s) on its ifid list\n",
                            ip6_sprintf(IA6_IN6(ia)), plen,
                            rap->ra_addr,
                            ip6_sprintf(IA6_IN6(rap->ra_addr)));
@@ -488,6 +488,22 @@
        }
 }
 
+void
+in6_purgeprefix(ifp)
+       struct ifnet *ifp;
+{
+       struct ifprefix *ifpr, *nextifpr;
+
+       /* delete prefixes before ifnet goes away */
+       for (ifpr = ifp->if_prefixlist; ifpr; ifpr = nextifpr) {
+               nextifpr = ifpr->ifpr_next;
+               if (ifpr->ifpr_prefix->sa_family != AF_INET6 ||
+                   ifpr->ifpr_type != IN6_PREFIX_RR)
+                       continue;
+               (void)delete_each_prefix(ifpr2rp(ifpr), PR_ORIG_KERNEL);
+       }
+}
+
 static void
 add_each_addr(struct socket *so, struct rr_prefix *rpp, struct rp_addr *rap)
 {
@@ -538,7 +554,7 @@
                 * log it and return.
                 */
                log(LOG_ERR, "in6_prefix.c: add_each_addr: addition of an addr"
-                   "%s/%d failed because there is already another addr %s/%d",
+                   "%s/%d failed because there is already another addr %s/%d\n",
                    ip6_sprintf(&ifra.ifra_addr.sin6_addr), rpp->rp_plen,
                    ip6_sprintf(IA6_IN6(ia6)),
                    in6_mask2len(&ia6->ia_prefixmask.sin6_addr));
@@ -551,7 +567,7 @@
                            , curproc);
        if (error != 0)
                log(LOG_ERR, "in6_prefix.c: add_each_addr: addition of an addr"
-                   "%s/%d failed because in6_control failed for error %d",
+                   "%s/%d failed because in6_control failed for error %d\n",
                    ip6_sprintf(&ifra.ifra_addr.sin6_addr), rpp->rp_plen,
                    error);
                return;
@@ -628,15 +644,14 @@
                                                 M_NOWAIT);
                if (rpp == NULL) {
                        log(LOG_ERR, "in6_prefix.c: rrpr_update:%d"
-                           ": ENOBUFS for rr_prefix", __LINE__);
+                           ": ENOBUFS for rr_prefix\n", __LINE__);
                        return(ENOBUFS);
                }
                /* initilization */
                *rpp = *new;
                LIST_INIT(&rpp->rp_addrhead);
                /*  move rp_addr entries of new to rpp */
-               while (new->rp_addrhead.lh_first != NULL)
-               {
+               while (new->rp_addrhead.lh_first != NULL) {
                        rap = LIST_FIRST(&new->rp_addrhead);
                        LIST_REMOVE(rap, ra_entry);
                        LIST_INSERT_HEAD(&rpp->rp_addrhead, rap, ra_entry);
@@ -728,7 +743,7 @@
                                         M_NOWAIT);
        if (*rapp == NULL) {
                log(LOG_ERR, "in6_prefix.c: init_newprefix:%d: ENOBUFS"
-                   "for rp_addr", __LINE__);
+                   "for rp_addr\n", __LINE__);
                return ENOBUFS;
        }
        bzero(*rapp, sizeof(*(*rapp)));
@@ -845,9 +860,8 @@
 }
 
 int
-delete_each_prefix(struct socket *so, struct rr_prefix *rpp, u_char origin)
+delete_each_prefix(struct rr_prefix *rpp, u_char origin)
 {
-       struct in6_aliasreq ifra;
        int error = 0;
 
        if (rpp->rp_origin > origin)
@@ -869,22 +883,7 @@
                }
                rap->ra_addr->ia6_ifpr = NULL;
 
-               bzero(&ifra, sizeof(ifra));
-               strncpy(ifra.ifra_name, if_name(rpp->rp_ifp),
-                       sizeof(ifra.ifra_name));
-               ifra.ifra_addr = rap->ra_addr->ia_addr;
-               ifra.ifra_dstaddr = rap->ra_addr->ia_dstaddr;
-               ifra.ifra_prefixmask = rap->ra_addr->ia_prefixmask;
-
-               error = in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
-                                   rpp->rp_ifp, curproc);
-               if (error != 0)
-                       log(LOG_ERR, "in6_prefix.c: delete_each_prefix:"
-                           "deletion of an addr %s/%d failed because"
-                           "in6_control failed for error %d",
-                           ip6_sprintf(&ifra.ifra_addr.sin6_addr),
-                           rpp->rp_plen, error);
-
+               in6_purgeaddr(&rap->ra_addr->ia_ifa, rpp->rp_ifp);
                free(rap, M_RR_ADDR);
        }
        rp_remove(rpp);
@@ -893,7 +892,7 @@
 }
 
 static void
-delete_prefixes(struct socket *so, struct ifnet *ifp, u_char origin)
+delete_prefixes(struct ifnet *ifp, u_char origin)
 {
        struct ifprefix *ifpr, *nextifpr;
 
@@ -904,7 +903,7 @@
                    ifpr->ifpr_type != IN6_PREFIX_RR)
                        continue;
                if (ifpr2rp(ifpr)->rp_statef_delmark)
-                       (void)delete_each_prefix(so, ifpr2rp(ifpr), origin);
+                       (void)delete_each_prefix(ifpr2rp(ifpr), origin);
        }
 }
 
@@ -931,7 +930,7 @@
                                                  rpp->rp_plen))
                                log(LOG_ERR, "in6_prefix.c: link_stray_ia6s:"
                                    "addr %s/%d already linked to a prefix"
-                                   "and it matches also %s/%d",
+                                   "and it matches also %s/%d\n",
                                    ip6_sprintf(IFA_IN6(ifa)), orpp->rp_plen,
                                    ip6_sprintf(RP_IN6(rpp)),
                                    rpp->rp_plen);
@@ -946,6 +945,7 @@
        return 0;
 }
 
+/* XXX assumes that permission is already checked by the caller */
 int
 in6_prefix_ioctl(struct socket *so, u_long cmd, caddr_t data,
                 struct ifnet *ifp)
@@ -974,7 +974,7 @@
                if (irr->irr_pltime > irr->irr_vltime) {
                        log(LOG_NOTICE,
                            "in6_prefix_ioctl: preferred lifetime"
-                           "(%ld) is greater than valid lifetime(%ld)",
+                           "(%ld) is greater than valid lifetime(%ld)\n",
                            (u_long)irr->irr_pltime, (u_long)irr->irr_vltime);
                        error = EINVAL;
                        break;
@@ -985,7 +985,7 @@
                                    != 0)
                                        goto failed;
                        if (cmd != SIOCAIFPREFIX_IN6)
-                               delete_prefixes(so, ifp, irr->irr_origin);
+                               delete_prefixes(ifp, irr->irr_origin);
                } else
                        return (EADDRNOTAVAIL);
        failed:
@@ -1009,7 +1009,7 @@
                if (ipr->ipr_pltime > ipr->ipr_vltime) {
                        log(LOG_NOTICE,
                            "in6_prefix_ioctl: preferred lifetime"
-                           "(%ld) is greater than valid lifetime(%ld)",
+                           "(%ld) is greater than valid lifetime(%ld)\n",
                            (u_long)ipr->ipr_pltime, (u_long)ipr->ipr_vltime);
                        error = EINVAL;
                        break;
@@ -1058,7 +1058,7 @@
                if (rpp == NULL || ifp != rpp->rp_ifp)
                        return (EADDRNOTAVAIL);
 
-               error = delete_each_prefix(so, rpp, ipr->ipr_origin);
+               error = delete_each_prefix(rpp, ipr->ipr_origin);
                break;
        }
        return error;
@@ -1079,13 +1079,9 @@
        while (rpp) {
                if (rpp->rp_expire && rpp->rp_expire < time_second) {
                        struct rr_prefix *next_rpp;
-                       struct socket so;
-
-                       /* XXX: init dummy so */
-                       bzero(&so, sizeof(so));
 
                        next_rpp = LIST_NEXT(rpp, rp_entry);
-                       delete_each_prefix(&so, rpp, PR_ORIG_KERNEL);
+                       delete_each_prefix(rpp, PR_ORIG_KERNEL);
                        rpp = next_rpp;
                        continue;
                }
diff -r 6ae0cfafa23f -r f88a15039902 sys/netinet6/in6_prefix.h
--- a/sys/netinet6/in6_prefix.h Fri Feb 04 14:21:33 2000 +0000
+++ b/sys/netinet6/in6_prefix.h Fri Feb 04 14:34:22 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in6_prefix.h,v 1.2 1999/12/13 15:17:22 itojun Exp $    */
+/*     $NetBSD: in6_prefix.h,v 1.3 2000/02/04 14:34:26 itojun Exp $    */
 
 /*
  * Copyright (C) 1995, 1996, 1997, 1998 and 1999 WIDE Project.
@@ -84,5 +84,4 @@
 extern struct rr_prhead rr_prefix;
 
 void in6_rr_timer __P((void *));
-int delete_each_prefix  __P((struct socket *so, struct rr_prefix *rpp,
-                            u_char origin));
+int delete_each_prefix  __P((struct rr_prefix *rpp, u_char origin));
diff -r 6ae0cfafa23f -r f88a15039902 sys/netinet6/in6_var.h
--- a/sys/netinet6/in6_var.h    Fri Feb 04 14:21:33 2000 +0000
+++ b/sys/netinet6/in6_var.h    Fri Feb 04 14:34:22 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in6_var.h,v 1.9 2000/02/02 23:28:10 thorpej Exp $      */
+/*     $NetBSD: in6_var.h,v 1.10 2000/02/04 14:34:26 itojun Exp $      */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -568,6 +568,7 @@
                              struct ifnet *ifp));



Home | Main Index | Thread Index | Old Index