]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib: fix setting of IPv4 multicast sockopts on OpenBSD
authorRenato Westphal <renato@opensourcerouting.org>
Thu, 4 Aug 2016 13:07:26 +0000 (10:07 -0300)
committerDonald Sharp <sharpd@cumulusnetwroks.com>
Mon, 8 Aug 2016 01:05:26 +0000 (21:05 -0400)
OpenBSD doesn't support the "ifindex hack" derived from RFC 1724 which
allows an ifindex to be encoded in the imr_interface field (in_addr)
of the ip_mreq structure. OpenBSD also doesn't support the RFC3678
Protocol-Independent socket API extensions, which allows an interface
to be specified by its ifindex. With that said, in OpenBSD we still need
to specify an interface by its IP address. This patch adds an exception
in the multicast sockopt functions to handle this case.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
lib/sockopt.c
lib/sockopt.h
ospfd/ospf_network.c
ripd/rip_interface.c

index 257271bc0b9a7ed4776bc4549a286935d938fce1..d8204936f9044737efd3edd8baa27e32b55e4cf6 100644 (file)
@@ -219,6 +219,7 @@ setsockopt_ipv6_tclass(int sock, int tclass)
 int
 setsockopt_ipv4_multicast(int sock,
                        int optname, 
+                       struct in_addr if_addr,
                        unsigned int mcast_addr,
                        unsigned int ifindex)
 {
@@ -279,18 +280,20 @@ setsockopt_ipv4_multicast(int sock,
 #elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK) /* #if OS_TYPE */ 
   /* standard BSD API */
 
-  struct in_addr m;
   struct ip_mreq mreq;
   int ret;
 
   assert(optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP);
 
-  m.s_addr = htonl(ifindex);
 
   memset (&mreq, 0, sizeof(mreq));
   mreq.imr_multiaddr.s_addr = mcast_addr;
-  mreq.imr_interface = m;
-  
+#if !defined __OpenBSD__
+  mreq.imr_interface.s_addr = htonl (ifindex);
+#else
+  mreq.imr_interface.s_addr = if_addr.s_addr;
+#endif
+
   ret = setsockopt (sock, IPPROTO_IP, optname, (void *)&mreq, sizeof(mreq));
   if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE))
     {
@@ -318,7 +321,7 @@ setsockopt_ipv4_multicast(int sock,
  * Set IP_MULTICAST_IF socket option in an OS-dependent manner.
  */
 int
-setsockopt_ipv4_multicast_if(int sock,
+setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr,
                        unsigned int ifindex)
 {
 
@@ -336,7 +339,11 @@ setsockopt_ipv4_multicast_if(int sock,
 #elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK)
   struct in_addr m;
 
-  m.s_addr = htonl(ifindex);
+#if !defined __OpenBSD__
+  m.s_addr = htonl (ifindex);
+#else
+  m.s_addr = if_addr.s_addr;
+#endif
 
   return setsockopt (sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&m, sizeof(m));
 #else
index cb14efc7baef2254bcd4a65c0195321645f02895..a597314c3d29f99191efd5272825f36b07ccfe0b 100644 (file)
@@ -83,9 +83,10 @@ extern int setsockopt_ipv6_tclass (int, int);
   (((af) == AF_INET) : SOPT_SIZE_CMSG_IFINDEX_IPV4() \
                     ? SOPT_SIZE_CMSG_PKTINFO_IPV6())
 
-extern int setsockopt_ipv4_multicast_if(int sock,
+extern int setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr,
                                     unsigned int ifindex);
 extern int setsockopt_ipv4_multicast(int sock, int optname,
+                                     struct in_addr if_addr,
                                      unsigned int mcast_addr,
                                     unsigned int ifindex);
 extern int setsockopt_ipv4_tos(int sock, int tos);
index 2f167a50a5e0fcaf459d675eaf8c00a93dc7b464..9f516d739055dc1f36854d2b1d0335ec6dc0d387 100644 (file)
@@ -53,7 +53,7 @@ ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p,
   int ret;
   
   ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP,
-                                   htonl (OSPF_ALLSPFROUTERS),
+                                   p->u.prefix4, htonl (OSPF_ALLSPFROUTERS),
                                    ifindex);
   if (ret < 0)
     zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, "
@@ -74,7 +74,7 @@ ospf_if_drop_allspfrouters (struct ospf *top, struct prefix *p,
   int ret;
 
   ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP,
-                                   htonl (OSPF_ALLSPFROUTERS),
+                                   p->u.prefix4, htonl (OSPF_ALLSPFROUTERS),
                                    ifindex);
   if (ret < 0)
     zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, "
@@ -95,7 +95,7 @@ ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, unsigned int
   int ret;
 
   ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP,
-                                   htonl (OSPF_ALLDROUTERS),
+                                   p->u.prefix4, htonl (OSPF_ALLDROUTERS),
                                    ifindex);
   if (ret < 0)
     zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, "
@@ -116,7 +116,7 @@ ospf_if_drop_alldrouters (struct ospf *top, struct prefix *p, unsigned int
   int ret;
 
   ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP,
-                                   htonl (OSPF_ALLDROUTERS),
+                                   p->u.prefix4, htonl (OSPF_ALLDROUTERS),
                                    ifindex);
   if (ret < 0)
     zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, "
@@ -151,7 +151,7 @@ ospf_if_ipmulticast (struct ospf *top, struct prefix *p, unsigned int ifindex)
     zlog_warn ("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s",
               top->fd, safe_strerror (errno));
 
-  ret = setsockopt_ipv4_multicast_if (top->fd, ifindex);
+  ret = setsockopt_ipv4_multicast_if (top->fd, p->u.prefix4, ifindex);
   if (ret < 0)
     zlog_warn("can't setsockopt IP_MULTICAST_IF(fd %d, addr %s, "
              "ifindex %u): %s",
index 6748e197da14d2d85a98f8bf22b73ea109a488ec..4499966ad086d15e8dddaf09ae926595febdde8d 100644 (file)
@@ -80,6 +80,7 @@ ipv4_multicast_join (int sock,
 
   ret = setsockopt_ipv4_multicast (sock,
                                   IP_ADD_MEMBERSHIP, 
+                                  ifa,
                                   group.s_addr, 
                                   ifindex); 
 
@@ -101,6 +102,7 @@ ipv4_multicast_leave (int sock,
 
   ret = setsockopt_ipv4_multicast (sock,
                                   IP_DROP_MEMBERSHIP, 
+                                  ifa,
                                   group.s_addr, 
                                   ifindex);
 
@@ -136,9 +138,13 @@ rip_interface_new (void)
 void
 rip_interface_multicast_set (int sock, struct connected *connected)
 {
+  struct in_addr addr;
+
   assert (connected != NULL);
-  
-  if (setsockopt_ipv4_multicast_if (sock, connected->ifp->ifindex) < 0)
+
+  addr = CONNECTED_ID(connected)->u.prefix4;
+
+  if (setsockopt_ipv4_multicast_if (sock, addr, connected->ifp->ifindex) < 0)
     {
       zlog_warn ("Can't setsockopt IP_MULTICAST_IF on fd %d to "
                 "ifindex %d for interface %s",