in6_control() with splnet()/splx(). I was being a bit paranoid
here. Following a cursory analysis of the code, this still looked
necessary. We don't spend a lot of time in these calls, so it
should not be too harmful to suspend network interrupts.
In in6_unlink_ifa(), call in6_delmulti() just once on each multicast
address (in6_multi). Previously, in6_unlink_ifa() called in6_delmulti()
on each in6_multi until in6_delmulti() removed the in6_multi from
the list and freed its memory. That's not justified: the multicast
list holds *one* reference. All other references belong to other
entities. We must wait to free the memory until the other entities
release their references, to protect against dereferencing a freed
in6_multi.
XXX I need to revisit in6_delmulti(), in6_unlink_ifa(), and friends,
XXX to pry apart the conditions where an in6_multi is removed from
XXX its list and where it is freed. Following my change, above,
XXX we still risk dereferencing a freed in6_multi.
Prevent in6_update_ifa() and in6_addremloop() from creating dangling
pointers to interfaces in the routing table. Previously, my NetBSD
tunnel concentrator, which adds and deletes a lot of P2P interfaces
with the same local address, crashed in 8 hours or less when it
dereferenced a dangling pointer to a deleted ifnet. Now, its uptime
is greater than 3 days.