Specify multicast interface
diff --git a/commons-jcs-core/pom.xml b/commons-jcs-core/pom.xml
index be95c6d..66fc82d 100644
--- a/commons-jcs-core/pom.xml
+++ b/commons-jcs-core/pom.xml
@@ -129,9 +129,6 @@
                   Several of the test cases rely on background tasks that are timing
                   sensitive.
               -->
-              <!-- You need to manually run these test cases. -->
-              <exclude>**/TestTCPLateralUnitTest.java</exclude>
-              <exclude>**/UDPDiscoveryUnitTest.java</exclude>
               <!-- Causes hang in Continuum -->
               <exclude>**/UDPDiscoverySenderUnitTest.java</exclude>
             </excludes>
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryAttributes.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryAttributes.java
index e89664e..8a8e58a 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryAttributes.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryAttributes.java
@@ -52,6 +52,9 @@
     /** udp discovery address */
     private String udpDiscoveryAddr = DEFAULT_UDP_DISCOVERY_ADDRESS;
 
+    /** udp discovery network interface */
+    private String udpDiscoveryInterface = null;
+
     /** udp discovery port */
     private int udpDiscoveryPort = DEFAULT_UDP_DISCOVERY_PORT;
 
@@ -132,6 +135,22 @@
     }
 
     /**
+     * @param udpDiscoveryInterface The udpDiscoveryInterface to set.
+     */
+    public void setUdpDiscoveryInterface( String udpDiscoveryInterface )
+    {
+        this.udpDiscoveryInterface = udpDiscoveryInterface;
+    }
+
+    /**
+     * @return Returns the udpDiscoveryInterface.
+     */
+    public String getUdpDiscoveryInterface()
+    {
+        return udpDiscoveryInterface;
+    }
+
+    /**
      * @param udpDiscoveryPort The udpDiscoveryPort to set.
      */
     public void setUdpDiscoveryPort( int udpDiscoveryPort )
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryReceiver.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryReceiver.java
index 0438ee3..7d2ea6a 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryReceiver.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryReceiver.java
@@ -68,11 +68,8 @@
     /** Service to get cache names and handle request broadcasts */
     private final UDPDiscoveryService service;
 
-    /** Address */
-    private final String multicastAddressString;
-
-    /** The port */
-    private final int multicastPort;
+    /** Multicast address */
+    private final InetAddress multicastAddress;
 
     /** Is it shutdown. */
     private boolean shutdown = false;
@@ -83,16 +80,17 @@
      * We determine out own host using InetAddress
      *<p>
      * @param service
+     * @param multicastInterfaceString
      * @param multicastAddressString
      * @param multicastPort
      * @throws IOException
      */
-    public UDPDiscoveryReceiver( UDPDiscoveryService service, String multicastAddressString, int multicastPort )
+    public UDPDiscoveryReceiver( UDPDiscoveryService service, String multicastInterfaceString,
+            String multicastAddressString, int multicastPort )
         throws IOException
     {
         this.service = service;
-        this.multicastAddressString = multicastAddressString;
-        this.multicastPort = multicastPort;
+        this.multicastAddress = InetAddress.getByName( multicastAddressString );
 
         // create a small thread pool to handle a barrage
         this.pooledExecutor = ThreadPoolManager.getInstance().createPool(
@@ -100,41 +98,53 @@
         		        WhenBlockedPolicy.DISCARDOLDEST, maxPoolSize),
         		"JCS-UDPDiscoveryReceiver-", Thread.MIN_PRIORITY);
 
-        log.info( "Constructing listener, [{0}:{1}]",
-                this.multicastAddressString, this.multicastPort );
+        log.info( "Constructing listener, [{0}:{1}]", multicastAddress, multicastPort );
 
-        createSocket( this.multicastAddressString, this.multicastPort );
+        createSocket( multicastInterfaceString, multicastAddress, multicastPort );
     }
 
     /**
      * Creates the socket for this class.
      * <p>
-     * @param multicastAddressString
+     * @param multicastInterfaceString
+     * @param multicastAddress
      * @param multicastPort
      * @throws IOException
      */
-    private void createSocket( String multicastAddressString, int multicastPort )
+    private void createSocket( String multicastInterfaceString, InetAddress multicastAddress,
+            int multicastPort )
         throws IOException
     {
         try
         {
             mSocket = new MulticastSocket( multicastPort );
-            InetAddress multicastAddress = InetAddress.getByName( multicastAddressString );
             if (log.isInfoEnabled())
             {
                 log.info( "Joining Group: [{0}]", multicastAddress );
             }
-            NetworkInterface multicastInterface = HostNameUtil.getMulticastNetworkInterface();
+
+            // Use dedicated interface if specified
+            NetworkInterface multicastInterface = null;
+            if (multicastInterfaceString != null)
+            {
+                multicastInterface = NetworkInterface.getByName(multicastInterfaceString);
+            }
+            else
+            {
+                multicastInterface = HostNameUtil.getMulticastNetworkInterface();
+            }
             if (multicastInterface != null)
             {
+                log.info("Using network interface {0}", multicastInterface.getDisplayName());
                 mSocket.setNetworkInterface(multicastInterface);
             }
+
             mSocket.joinGroup( multicastAddress );
         }
         catch ( IOException e )
         {
-            log.error( "Could not bind to multicast address [{0}:{1}]",
-                    InetAddress.getByName( multicastAddressString ), multicastPort, e );
+            log.error( "Could not bind to multicast address [{0}:{1}]", multicastAddress,
+                    multicastPort, e );
             throw e;
         }
     }
@@ -338,16 +348,19 @@
     @Override
     public void shutdown()
     {
-        try
+        if (!shutdown)
         {
-            shutdown = true;
-            mSocket.leaveGroup( InetAddress.getByName( multicastAddressString ) );
-            mSocket.close();
-            pooledExecutor.shutdownNow();
-        }
-        catch ( IOException e )
-        {
-            log.error( "Problem closing socket" );
+            try
+            {
+                shutdown = true;
+                mSocket.leaveGroup( multicastAddress );
+                mSocket.close();
+                pooledExecutor.shutdownNow();
+            }
+            catch ( IOException e )
+            {
+                log.error( "Problem closing socket" );
+            }
         }
     }
 }
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryService.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryService.java
index 04ac502..107851a 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryService.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryService.java
@@ -94,8 +94,10 @@
         try
         {
             // todo need some kind of recovery here.
-            receiver = new UDPDiscoveryReceiver( this, getUdpDiscoveryAttributes().getUdpDiscoveryAddr(),
-                                                 getUdpDiscoveryAttributes().getUdpDiscoveryPort() );
+            receiver = new UDPDiscoveryReceiver( this,
+                    getUdpDiscoveryAttributes().getUdpDiscoveryInterface(),
+                    getUdpDiscoveryAttributes().getUdpDiscoveryAddr(),
+                    getUdpDiscoveryAttributes().getUdpDiscoveryPort() );
         }
         catch ( IOException e )
         {
diff --git a/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/discovery/UDPDiscoverySenderUnitTest.java b/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/discovery/UDPDiscoverySenderUnitTest.java
index c47b52e..e88930b 100644
--- a/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/discovery/UDPDiscoverySenderUnitTest.java
+++ b/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/discovery/UDPDiscoverySenderUnitTest.java
@@ -60,7 +60,7 @@
         throws Exception
     {
         super.setUp();
-        receiver = new UDPDiscoveryReceiver( null, ADDRESS, PORT );
+        receiver = new UDPDiscoveryReceiver( null, null, ADDRESS, PORT );
         sender = new UDPDiscoverySender( ADDRESS, PORT );
     }
 
diff --git a/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryUnitTest.java b/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryUnitTest.java
index 6a83885..c070a53 100644
--- a/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryUnitTest.java
+++ b/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryUnitTest.java
@@ -52,8 +52,10 @@
         service.addDiscoveryListener( discoveryListener );
 
         // create a receiver with the service
-        UDPDiscoveryReceiver receiver = new UDPDiscoveryReceiver( service, attributes.getUdpDiscoveryAddr(), attributes
-            .getUdpDiscoveryPort() );
+        UDPDiscoveryReceiver receiver = new UDPDiscoveryReceiver( service,
+                null,
+                attributes.getUdpDiscoveryAddr(),
+                attributes.getUdpDiscoveryPort() );
         Thread t = new Thread( receiver );
         t.start();
 
diff --git a/xdocs/LateralUDPDiscovery.xml b/xdocs/LateralUDPDiscovery.xml
index cf41eee..b19dbc6 100644
--- a/xdocs/LateralUDPDiscovery.xml
+++ b/xdocs/LateralUDPDiscovery.xml
@@ -67,6 +67,29 @@
 jcs.auxiliary.LTCP.attributes.UdpDiscoveryEnabled=true
         ]]></source>
       </subsection>
+      <subsection name="Multi-homed hosts">
+        <p>
+          On machines that have several network interfaces, it might be
+          desirable to fix the interface that is used for multicast.
+          For this purpose, the network interface can be specified in the 
+          configuration (see below).
+        </p>
+        <p>
+          If the network interface is not specified, JCS tries to detect a 
+          suitable interface. The selected interface is logged on INFO level.
+          Search for the message "Using network interface" in your log file.
+        </p>
+        <source><![CDATA[
+jcs.auxiliary.LTCP=org.apache.commons.jcs.auxiliary.lateral.socket.tcp.LateralTCPCacheFactory
+jcs.auxiliary.LTCP.attributes=org.apache.commons.jcs.auxiliary.lateral.socket.tcp.TCPLateralCacheAttributes
+jcs.auxiliary.LTCP.attributes.TcpListenerPort=1110
+jcs.auxiliary.LTCP.attributes.PutOnlyMode=true
+jcs.auxiliary.LTCP.attributes.UdpDiscoveryInterface=en0
+jcs.auxiliary.LTCP.attributes.UdpDiscoveryAddr=228.5.6.8
+jcs.auxiliary.LTCP.attributes.UdpDiscoveryPort=6780
+jcs.auxiliary.LTCP.attributes.UdpDiscoveryEnabled=true
+        ]]></source>
+      </subsection>
     </section>
   </body>
 </document>