$OpenBSD: patch-lib_sockopt_c,v 1.4 2017/11/03 14:28:43 sthen Exp $

Index: lib/sockopt.c
--- lib/sockopt.c.orig
+++ lib/sockopt.c
@@ -21,7 +21,7 @@
 
 #include <zebra.h>
 
-#ifdef SUNOS_5
+#if defined(SUNOS_5) || defined(__OpenBSD__)
 #include <ifaddrs.h>
 #endif
 
@@ -281,17 +281,45 @@ setsockopt_ipv4_multicast(int sock,
   /* #elif  defined(BOGON_NIX) && EXAMPLE_VERSION_CODE > -100000 */
   /* Add your favourite OS here! */
 
-#elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK) /* #if OS_TYPE */ 
+#elif defined(__OpenBSD__) || defined(HAVE_BSD_STRUCT_IP_MREQ_HACK) /* #if OS_TYPE */ 
   /* standard BSD API */
 
   struct in_addr m;
   struct ip_mreq mreq;
   int ret;
+#if defined(HAVE_BSD_STRUCT_IP_MREQ_HACK)
+  assert(optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP);
+  m.s_addr = htonl(ifindex);
+#else
+  char ifname[IF_NAMESIZE];
+  struct ifaddrs *ifa, *ifap;
 
   assert(optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP);
 
-  m.s_addr = htonl(ifindex);
+  if (if_indextoname(ifindex, ifname) == NULL)
+    return -1;
 
+  if (getifaddrs(&ifa) != 0)
+    return -1;
+
+  for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next)
+    {
+      struct sockaddr_in *sa;
+
+      if (strcmp(ifap->ifa_name, ifname) != 0)
+        continue;
+      if (ifap->ifa_addr->sa_family != AF_INET)
+        continue;
+      sa = (struct sockaddr_in*)ifap->ifa_addr;
+      memcpy(&m, &sa->sin_addr, sizeof(m));
+      break;
+    }
+
+  freeifaddrs(ifa);
+  if (!ifap) /* This means we did not find an IP */
+    return -1;
+#endif
+
   memset (&mreq, 0, sizeof(mreq));
   mreq.imr_multiaddr.s_addr = mcast_addr;
   mreq.imr_interface = m;
@@ -343,7 +371,7 @@ setsockopt_ipv4_multicast_if(int sock, ifindex_t ifind
   m.s_addr = htonl(ifindex);
 
   return setsockopt (sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&m, sizeof(m));
-#elif defined(SUNOS_5)
+#elif defined(SUNOS_5) || defined(__OpenBSD__)
   char ifname[IF_NAMESIZE];
   struct ifaddrs *ifa, *ifap;
   struct in_addr ifaddr;
