[ospfd] Fix multicast membership drop bug

2006-06-15 Paul Jakma <paul.jakma@sun.com>

	* Reported by Milan Koci
	* ospf_interface.h: (struct ospf_if_info) Add reference counts
	  for multicast group memberships. Add various macros to help
	  manipulate/check membership state.
	* ospf_interface.c: (ospf_if_set_multicast) Maintain the
	  ospf_if_info reference counts, and only actually drop
	  memberships if it hits 0, to avoid losing membership when
	  OSPF is disabled on an interface with multiple active OSPF
	  interfaces.
	* ospf_packet.c: (ospf_{hello,read}) Use the new macros to
	  check/set
	  multicast membership.
	* ospf_vty.c: (show_ip_ospf_interface_sub) ditto.
diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h
index 3c75940..5a825ea 100644
--- a/ospfd/ospf_interface.h
+++ b/ospfd/ospf_interface.h
@@ -68,11 +68,19 @@
   DECLARE_IF_PARAM (int, auth_type);               /* OSPF authentication type */
 };
 
+enum
+{
+  MEMBER_ALLROUTERS = 0,
+  MEMBER_DROUTERS,
+  MEMBER_MAX,
+};
+
 struct ospf_if_info
 {
   struct ospf_if_params *def_params;
   struct route_table *params;
   struct route_table *oifs;
+  unsigned int membership_counts[MEMBER_MAX];	/* multicast group refcnts */
 };
 
 struct ospf_interface;
@@ -132,8 +140,20 @@
 
   /* To which multicast groups do we currently belong? */
   u_char multicast_memberships;
-#define MEMBER_ALLROUTERS	0x1
-#define MEMBER_DROUTERS		0x2
+#define OI_MEMBER_FLAG(M) (1 << (M))
+#define OI_MEMBER_COUNT(O,M) (IF_OSPF_IF_INFO(oi->ifp)->membership_counts[(M)])
+#define OI_MEMBER_CHECK(O,M) \
+    (CHECK_FLAG((O)->multicast_memberships, OI_MEMBER_FLAG(M)))
+#define OI_MEMBER_JOINED(O,M) \
+  do { \
+    SET_FLAG ((O)->multicast_memberships, OI_MEMBER_FLAG(M)); \
+    IF_OSPF_IF_INFO((O)->ifp)->membership_counts[(M)]++; \
+  } while (0)
+#define OI_MEMBER_LEFT(O,M) \
+  do { \
+    UNSET_FLAG ((O)->multicast_memberships, OI_MEMBER_FLAG(M)); \
+    IF_OSPF_IF_INFO((O)->ifp)->membership_counts[(M)]--; \
+  } while (0)
 
   struct prefix *address;		/* Interface prefix */
   struct connected *connected;          /* Pointer to connected */