--- sockopt.c.orig	2007-10-09 11:48:31.000000000 +0300
+++ sockopt.c	2007-10-09 09:45:13.000000000 +0300
@@ -214,13 +214,13 @@
 #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
   /* This is better because it uses ifindex directly */
   struct ip_mreqn mreqn;
+  struct group_req gr;
+  struct sockaddr_in *si;
   int ret;
   
   switch (optname)
     {
     case IP_MULTICAST_IF:
-    case IP_ADD_MEMBERSHIP:
-    case IP_DROP_MEMBERSHIP:
       memset (&mreqn, 0, sizeof(mreqn));
 
       if (mcast_addr)
@@ -233,6 +233,35 @@
       
       ret = setsockopt(sock, IPPROTO_IP, optname,
 		       (void *)&mreqn, sizeof(mreqn));
+      return ret;
+      break;
+
+    case IP_ADD_MEMBERSHIP:
+    case IP_DROP_MEMBERSHIP:
+      if (ifindex)
+        {
+          memset (&gr, 0, sizeof(gr));
+	  si = (struct sockaddr_in *)&gr.gr_group;
+	  gr.gr_interface = ifindex;
+          if (mcast_addr)
+            si->sin_family = AF_INET;
+            si->sin_len = sizeof(struct sockaddr_in);
+	    si->sin_addr.s_addr = mcast_addr;
+          if (optname == IP_ADD_MEMBERSHIP)
+            ret = setsockopt(sock, IPPROTO_IP, MCAST_JOIN_GROUP, (void *)&gr, sizeof(gr));
+          else
+            ret = setsockopt(sock, IPPROTO_IP, MCAST_LEAVE_GROUP, (void *)&gr, sizeof(gr));
+        }
+      else
+        {
+          memset (&mreqn, 0, sizeof(mreqn));
+          if (mcast_addr)
+	    mreqn.imr_multiaddr.s_addr = mcast_addr;
+	  mreqn.imr_address = if_addr;
+      
+          ret = setsockopt(sock, IPPROTO_IP, optname,
+		       (void *)&mreqn, sizeof(mreqn));
+        }
       if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE))
         {
 	  /* see above: handle possible problem when interface comes back up */
@@ -241,16 +270,23 @@
 		    "re-add (fd %d, ifaddr %s, mcast %s, ifindex %u)",
 		    sock,
 		    inet_ntop(AF_INET, &if_addr, buf[0], sizeof(buf[0])),
-		    inet_ntop(AF_INET, &mreqn.imr_multiaddr,
-			      buf[1], sizeof(buf[1])), ifindex);
-	  setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
-		     (void *)&mreqn, sizeof(mreqn));
-	  ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
-			   (void *)&mreqn, sizeof(mreqn));
+		    inet_ntop(AF_INET, &mcast_addr, buf[1], sizeof(buf[1])),
+                    ifindex);
+          if (ifindex)
+            {
+	      setsockopt(sock, IPPROTO_IP, MCAST_LEAVE_GROUP, (void *)&gr, sizeof(gr));
+	      ret = setsockopt(sock, IPPROTO_IP, MCAST_JOIN_GROUP, (void *)&gr, sizeof(gr));
+            }
+          else
+            {
+	      setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, (void *)&mreqn, sizeof(mreqn));
+	      ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreqn, sizeof(mreqn));
+            }
         }
       return ret;
       break;
 
+
     default:
       /* Can out and give an understandable error */
       errno = EINVAL;
