Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-1-5]: src/sys/netinet Pullup 1.65 [enami]:
details: https://anonhg.NetBSD.org/src/rev/fc5a4fcecf11
branches: netbsd-1-5
changeset: 489754:fc5a4fcecf11
user: tv <tv%NetBSD.org@localhost>
date: Tue Oct 17 00:45:36 2000 +0000
description:
Pullup 1.65 [enami]:
- Keep track of allhost multicast address record we joined into
each in_ifaddr and delete it when an address is purged.
- Don't simply try to delete a multicast address record listed in the
ia_multiaddrs. It results a dangling pointer. Let who holds a
reference to it to delete it.
Also 1.64 [itojun, req by enami]:
implement multicast kludge table for IPv4.
- when all the interface address is removed from an interface, and there's
multicast groups still left joined, keep it in kludge table.
- when an interface address is added again, recover multicast groups from
kludge table.
this will avoid problem with dangling in_ifaddr on pcmcia card removal,
due to the link from multicast group info (in_multi).
diffstat:
sys/netinet/in.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 108 insertions(+), 3 deletions(-)
diffs (159 lines):
diff -r 588e8b165b44 -r fc5a4fcecf11 sys/netinet/in.c
--- a/sys/netinet/in.c Mon Oct 16 23:56:31 2000 +0000
+++ b/sys/netinet/in.c Tue Oct 17 00:45:36 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: in.c,v 1.61.4.2 2000/10/06 07:00:37 itojun Exp $ */
+/* $NetBSD: in.c,v 1.61.4.3 2000/10/17 00:45:36 tv Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -145,6 +145,13 @@
int hostzeroisbroadcast = HOSTZEROBROADCAST;
/*
+ * This list is used to keep track of in_multi chains which belong to
+ * deleted interface addresses. We use in_ifaddr so that a chain head
+ * won't be deallocated until all multicast address record are deleted.
+ */
+static TAILQ_HEAD(, in_ifaddr) in_mk = TAILQ_HEAD_INITIALIZER(in_mk);
+
+/*
* Return 1 if an internet address is for a ``local'' host
* (one to which we have a connection). If subnetsarelocal
* is true, this includes other subnets of the local net.
@@ -557,6 +564,15 @@
TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
IFAFREE(&ia->ia_ifa);
TAILQ_REMOVE(&in_ifaddr, ia, ia_list);
+ if (ia->ia_allhosts != NULL)
+ in_delmulti(ia->ia_allhosts);
+ if (LIST_FIRST(&ia->ia_multiaddrs) != NULL &&
+ /*
+ * If the interface is going away, don't bother to save
+ * the multicast entries.
+ */
+ ifp->if_output != if_nulloutput)
+ in_savemkludge(ia);
IFAFREE(&ia->ia_ifa);
in_setmaxmtu();
}
@@ -573,6 +589,7 @@
continue;
in_purgeaddr(ifa, ifp);
}
+ in_purgemkludge(ifp);
}
/*
@@ -864,14 +881,19 @@
if (error == EEXIST)
error = 0;
/*
+ * recover multicast kludge entry, if there is.
+ */
+ if (ifp->if_flags & IFF_MULTICAST)
+ in_restoremkludge(ia, ifp);
+ /*
* If the interface supports multicast, join the "all hosts"
* multicast group on that interface.
*/
- if (ifp->if_flags & IFF_MULTICAST) {
+ if ((ifp->if_flags & IFF_MULTICAST) != 0 && ia->ia_allhosts == NULL) {
struct in_addr addr;
addr.s_addr = INADDR_ALLHOSTS_GROUP;
- in_addmulti(&addr, ifp);
+ ia->ia_allhosts = in_addmulti(&addr, ifp);
}
return (error);
bad:
@@ -920,6 +942,89 @@
}
/*
+ * Multicast address kludge:
+ * If there were any multicast addresses attached to this interface address,
+ * either move them to another address on this interface, or save them until
+ * such time as this interface is reconfigured for IPv4.
+ */
+void
+in_savemkludge(oia)
+ struct in_ifaddr *oia;
+{
+ struct in_ifaddr *ia;
+ struct in_multi *inm, *next;
+
+ IFP_TO_IA(oia->ia_ifp, ia);
+ if (ia) { /* there is another address */
+ for (inm = oia->ia_multiaddrs.lh_first; inm; inm = next){
+ next = inm->inm_list.le_next;
+ IFAFREE(&inm->inm_ia->ia_ifa);
+ IFAREF(&ia->ia_ifa);
+ inm->inm_ia = ia;
+ LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm, inm_list);
+ }
+ } else { /* last address on this if deleted, save */
+ TAILQ_INSERT_TAIL(&in_mk, oia, ia_list);
+ IFAREF(&oia->ia_ifa);
+ }
+}
+
+/*
+ * Continuation of multicast address hack:
+ * If there was a multicast group list previously saved for this interface,
+ * then we re-attach it to the first address configured on the i/f.
+ */
+void
+in_restoremkludge(ia, ifp)
+ struct in_ifaddr *ia;
+ struct ifnet *ifp;
+{
+ struct in_ifaddr *oia;
+
+ for (oia = TAILQ_FIRST(&in_mk); oia != NULL;
+ oia = TAILQ_NEXT(oia, ia_list)) {
+ if (oia->ia_ifp == ifp) {
+ struct in_multi *inm, *next;
+
+ for (inm = LIST_FIRST(&oia->ia_multiaddrs);
+ inm != NULL; inm = next) {
+ next = LIST_NEXT(inm, inm_list);
+ IFAFREE(&inm->inm_ia->ia_ifa);
+ IFAREF(&ia->ia_ifa);
+ inm->inm_ia = ia;
+ LIST_INSERT_HEAD(&ia->ia_multiaddrs,
+ inm, inm_list);
+ }
+ TAILQ_REMOVE(&in_mk, oia, ia_list);
+ IFAFREE(&oia->ia_ifa);
+ break;
+ }
+ }
+}
+
+void
+in_purgemkludge(ifp)
+ struct ifnet *ifp;
+{
+ struct in_ifaddr *oia;
+
+ for (oia = TAILQ_FIRST(&in_mk); oia != NULL;
+ oia = TAILQ_NEXT(oia, ia_list)) {
+ if (oia->ia_ifp != ifp)
+ continue;
+
+ /*
+ * Leaving from all multicast groups joined through
+ * this interface is done via in_pcbpurgeif().
+ */
+
+ TAILQ_REMOVE(&in_mk, oia, ia_list);
+ IFAFREE(&oia->ia_ifa);
+ break;
+ }
+}
+
+/*
* Add an address to the list of IP multicast addresses for a given interface.
*/
struct in_multi *
Home |
Main Index |
Thread Index |
Old Index