summaryrefslogtreecommitdiff
path: root/sys/netinet6
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2001-07-18 12:50:45 +0000
committerJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2001-07-18 12:50:45 +0000
commit1b9e8efd6e3c626840081750789297daf99ccb76 (patch)
treec156e1459f4011e1bf645beb039ce7a748b5d898 /sys/netinet6
parentd4faff719766b6a4ad20c1a3b81b5166dd8c3cb7 (diff)
avoid using malloc() during interupt context for multicast kludge entry.
allocate it on interface initialization.
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/in6.c56
-rw-r--r--sys/netinet6/in6_ifattach.c7
-rw-r--r--sys/netinet6/in6_var.h3
3 files changed, 48 insertions, 18 deletions
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 6af82df76f3..656f98caf7a 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: in6.c,v 1.28 2001/06/09 06:43:37 angelos Exp $ */
-/* $KAME: in6.c,v 1.176 2001/02/16 12:49:45 itojun Exp $ */
+/* $OpenBSD: in6.c,v 1.29 2001/07/18 12:50:44 itojun Exp $ */
+/* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -87,9 +87,9 @@
#include <netinet/in_var.h>
#include <netinet/if_ether.h>
-#include <netinet6/nd6.h>
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
+#include <netinet6/nd6.h>
#include <netinet6/mld6_var.h>
#include <netinet6/ip6_mroute.h>
#include <netinet6/in6_ifattach.h>
@@ -1253,10 +1253,12 @@ in6_savemkludge(oia)
} else { /* last address on this if deleted, save */
struct multi6_kludge *mk;
- mk = malloc(sizeof(*mk), M_IPMADDR, M_WAITOK);
-
- LIST_INIT(&mk->mk_head);
- mk->mk_ifp = oia->ia_ifp;
+ for (mk = in6_mk.lh_first; mk; mk = mk->mk_entry.le_next) {
+ if (mk->mk_ifp == oia->ia_ifp)
+ break;
+ }
+ if (mk == NULL) /* this should not happen! */
+ panic("in6_savemkludge: no kludge space");
for (in6m = oia->ia6_multiaddrs.lh_first; in6m; in6m = next){
next = in6m->in6m_entry.le_next;
@@ -1264,12 +1266,6 @@ in6_savemkludge(oia)
in6m->in6m_ia = NULL;
LIST_INSERT_HEAD(&mk->mk_head, in6m, in6m_entry);
}
-
- if (mk->mk_head.lh_first != NULL) {
- LIST_INSERT_HEAD(&in6_mk, mk, mk_entry);
- } else {
- FREE(mk, M_IPMADDR);
- }
}
}
@@ -1296,13 +1292,43 @@ in6_restoremkludge(ia, ifp)
LIST_INSERT_HEAD(&ia->ia6_multiaddrs,
in6m, in6m_entry);
}
- LIST_REMOVE(mk, mk_entry);
- free(mk, M_IPMADDR);
+ LIST_INIT(&mk->mk_head);
break;
}
}
}
+/*
+ * Allocate space for the kludge at interface initialization time.
+ * Formerly, we dynamically allocated the space in in6_savemkludge() with
+ * malloc(M_WAITOK). However, it was wrong since the function could be called
+ * under an interrupt context (software timer on address lifetime expiration).
+ * Also, we cannot just give up allocating the strucutre, since the group
+ * membership structure is very complex and we need to keep it anyway.
+ * Of course, this function MUST NOT be called under an interrupt context.
+ * Specifically, it is expected to be called only from in6_ifattach(), though
+ * it is a global function.
+ */
+void
+in6_createmkludge(ifp)
+ struct ifnet *ifp;
+{
+ struct multi6_kludge *mk;
+
+ for (mk = in6_mk.lh_first; mk; mk = mk->mk_entry.le_next) {
+ /* If we've already had one, do not allocate. */
+ if (mk->mk_ifp == ifp)
+ return;
+ }
+
+ mk = malloc(sizeof(*mk), M_IPMADDR, M_WAITOK);
+
+ bzero(mk, sizeof(*mk));
+ LIST_INIT(&mk->mk_head);
+ mk->mk_ifp = ifp;
+ LIST_INSERT_HEAD(&in6_mk, mk, mk_entry);
+}
+
void
in6_purgemkludge(ifp)
struct ifnet *ifp;
diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c
index df723fccad1..5e49c126921 100644
--- a/sys/netinet6/in6_ifattach.c
+++ b/sys/netinet6/in6_ifattach.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: in6_ifattach.c,v 1.17 2001/06/09 06:43:37 angelos Exp $ */
-/* $KAME: in6_ifattach.c,v 1.112 2001/02/10 15:44:59 jinmei Exp $ */
+/* $OpenBSD: in6_ifattach.c,v 1.18 2001/07/18 12:50:44 itojun Exp $ */
+/* $KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -630,6 +630,9 @@ in6_ifattach(ifp, altifp)
icmp6_ifstatmax = if_indexlim;
}
+ /* create a multicast kludge storage (if we have not had one) */
+ in6_createmkludge(ifp);
+
/*
* quirks based on interface type
*/
diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h
index bf038cf403d..adad5456777 100644
--- a/sys/netinet6/in6_var.h
+++ b/sys/netinet6/in6_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_var.h,v 1.12 2001/02/16 14:45:12 itojun Exp $ */
+/* $OpenBSD: in6_var.h,v 1.13 2001/07/18 12:50:44 itojun Exp $ */
/* $KAME: in6_var.h,v 1.55 2001/02/16 12:49:45 itojun Exp $ */
/*
@@ -567,6 +567,7 @@ void in6_purgeaddr __P((struct ifaddr *, struct ifnet *));
void in6_savemkludge __P((struct in6_ifaddr *));
void in6_setmaxmtu __P((void));
void in6_restoremkludge __P((struct in6_ifaddr *, struct ifnet *));
+void in6_createmkludge __P((struct ifnet *));
void in6_purgemkludge __P((struct ifnet *));
struct in6_ifaddr *in6ifa_ifpforlinklocal __P((struct ifnet *, int));
struct in6_ifaddr *in6ifa_ifpwithaddr __P((struct ifnet *,