2005-02-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu>

	* ospf_interface.h: Improve passive_interface comment.  Add new
	  multicast_memberships bitmask to struct ospf_interface to track
	  active multicast subscriptions.  Declare new function
	  ospf_if_set_multicast.
	* ospf_interface.c: (ospf_if_set_multicast) New function to configure
	  multicast memberships properly based on the current
	  multicast_memberships status and the current values of the
	  ospf_interface state, type, and passive_interface status.
	  (ospf_if_up) Remove call to ospf_if_add_allspfrouters (this is
	  now handled by ism_change_state's call to ospf_if_set_multicast).
	  (ospf_if_down) Remove call to ospf_if_drop_allspfrouters (now
	  handled by ism_change_state).
	* ospf_ism.c: (ospf_dr_election) Remove logic to join or leave
	  the DRouters multicast group (now handled by ism_change_state's call
	  to ospf_if_set_multicast).
	  (ism_change_state) Add call to ospf_if_set_multicast to change
	  multicast memberships as necessary to reflect the new interface state.
	* ospf_packet.c: (ospf_hello) When a Hello packet is received on a
	  passive interface: 1. Increase the severity of the error message
	  from LOG_INFO to LOG_WARNING; 2. Add more information to the error
	  message (packet destination address and interface address);
	  and 3. If the packet was sent to ospf-all-routers, then try
	  to fix the multicast group memberships.
	  (ospf_read) When a packet is received on an interface whose state
	  is ISM_Down, enhance the warning message to show the packet
	  destination address, and try to update/fix the multicast group
	  memberships if the packet was sent to a multicast address.
	  When a packet is received for ospf-designated-routers, but the
	  current interface state is not DR or BDR, then increase the
	  severity level of the error message from LOG_INFO to LOG_WARNING,
	  and try to fix the multicast group memberships.
	* ospf_vty.c: (ospf_passive_interface) Call ospf_if_set_multicast for
	  any ospf interface that may have changed from active to passive.
	  (no_ospf_passive_interface) Call ospf_if_set_multicast for
	  any ospf interface that may have changed from passive to active.
	  (show_ip_ospf_interface_sub) Show multicast group memberships.
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index b4c12ff..e3f8f1b 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -260,6 +260,7 @@
  struct in_addr addr;
  int ret;
  struct ospf_if_params *params;
+ struct route_node *rn;
 
  ifp = if_lookup_by_name (argv[0]);
  
@@ -287,7 +288,28 @@
 
   SET_IF_PARAM (params, passive_interface);
   params->passive_interface = OSPF_IF_PASSIVE;
- 
+
+  /* XXX We should call ospf_if_set_multicast on exactly those
+   * interfaces for which the passive property changed.  It is too much
+   * work to determine this set, so we do this for every interface.
+   * This is safe and reasonable because ospf_if_set_multicast uses a
+   * record of joined groups to avoid systems calls if the desired
+   * memberships match the current memership.
+   */
+  for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next (rn))
+    {
+      struct ospf_interface *oi = rn->info;
+
+      if (oi && (OSPF_IF_PARAM(oi, passive_interface) == OSPF_IF_PASSIVE))
+        ospf_if_set_multicast(oi);
+    }
+  /*
+   * XXX It is not clear what state transitions the interface needs to
+   * undergo when going from active to passive.  Fixing this will
+   * require precise identification of interfaces having such a
+   * transition.
+   */
+
  return CMD_SUCCESS;
 }
 
@@ -308,6 +330,7 @@
   struct in_addr addr;
   struct ospf_if_params *params;
   int ret;
+  struct route_node *rn;
     
   ifp = if_lookup_by_name (argv[0]);
   
@@ -342,7 +365,22 @@
       ospf_free_if_params (ifp, addr);
       ospf_if_update_params (ifp, addr);
     }
-  
+
+  /* XXX We should call ospf_if_set_multicast on exactly those
+   * interfaces for which the passive property changed.  It is too much
+   * work to determine this set, so we do this for every interface.
+   * This is safe and reasonable because ospf_if_set_multicast uses a
+   * record of joined groups to avoid systems calls if the desired
+   * memberships match the current memership.
+   */
+  for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next (rn))
+    {
+      struct ospf_interface *oi = rn->info;
+
+      if (oi && (OSPF_IF_PARAM(oi, passive_interface) == OSPF_IF_ACTIVE))
+        ospf_if_set_multicast(oi);
+    }
+
   return CMD_SUCCESS;
 }
 
@@ -2628,6 +2666,17 @@
 		       inet_ntoa (nbr->address.u.prefix4), VTY_NEWLINE);
 	    }
 	}
+
+      vty_out (vty, "  Multicast group memberships:");
+      if (CHECK_FLAG(oi->multicast_memberships, MEMBER_ALLROUTERS))
+        vty_out (vty, " OSPFAllRouters");
+      if (CHECK_FLAG(oi->multicast_memberships, MEMBER_DROUTERS))
+        vty_out (vty, " OSPFDesignatedRouters");
+      if (!CHECK_FLAG(oi->multicast_memberships,
+		      MEMBER_ALLROUTERS|MEMBER_DROUTERS))
+        vty_out (vty, " <None>");
+      vty_out (vty, "%s", VTY_NEWLINE);
+
       vty_out (vty, "  Timer intervals configured,");
       vty_out (vty, " Hello %d, Dead %d, Wait %d, Retransmit %d%s",
 	       OSPF_IF_PARAM (oi, v_hello), OSPF_IF_PARAM (oi, v_wait),