Announce: https://lists.quagga.net/pipermail/quagga-users/2016-March/014293.html ChangeLog: http://savannah.spinellicreations.com/quagga/quagga-1.0.20160315.changelog.txt http://savannah.spinellicreations.com/quagga/quagga-1.0.20160309.changelog.txt Note that this update brings a fix for CVE-2016-2342. This vulnerability affects quagga MPLS VPN setups which probably aren't possible on OpenBSD.
237 lines
8.0 KiB
Plaintext
237 lines
8.0 KiB
Plaintext
$OpenBSD: patch-lib_sockopt_c,v 1.2 2016/03/22 12:57:54 jca Exp $
|
|
|
|
Revert 69bf3a39; does not work on at least (Open/Net)BSD.
|
|
This can be put back if we get RFC3678 support.
|
|
|
|
--- lib/sockopt.c.orig Wed Mar 16 00:17:17 2016
|
|
+++ lib/sockopt.c Mon Mar 21 01:42:18 2016
|
|
@@ -197,7 +197,7 @@ setsockopt_ipv6_tclass(int sock, int tclass)
|
|
|
|
/*
|
|
* Process multicast socket options for IPv4 in an OS-dependent manner.
|
|
- * Supported options are IP_{ADD,DROP}_MEMBERSHIP.
|
|
+ * Supported options are IP_MULTICAST_IF and IP_{ADD,DROP}_MEMBERSHIP.
|
|
*
|
|
* Many operating systems have a limit on the number of groups that
|
|
* can be joined per socket (where each group and local address
|
|
@@ -217,132 +217,121 @@ setsockopt_ipv6_tclass(int sock, int tclass)
|
|
* allow leaves, or implicitly leave all groups joined to down interfaces.
|
|
*/
|
|
int
|
|
-setsockopt_ipv4_multicast(int sock,
|
|
+setsockopt_multicast_ipv4(int sock,
|
|
int optname,
|
|
+ struct in_addr if_addr /* required */,
|
|
unsigned int mcast_addr,
|
|
- ifindex_t ifindex)
|
|
+ ifindex_t ifindex /* optional: if non-zero, may be
|
|
+ used instead of if_addr */)
|
|
{
|
|
-#ifdef HAVE_RFC3678
|
|
- struct group_req gr;
|
|
- struct sockaddr_in *si;
|
|
- int ret;
|
|
- memset (&gr, 0, sizeof(gr));
|
|
- si = (struct sockaddr_in *)&gr.gr_group;
|
|
- gr.gr_interface = ifindex;
|
|
- si->sin_family = AF_INET;
|
|
-#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
|
- si->sin_len = sizeof(struct sockaddr_in);
|
|
-#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
|
|
- si->sin_addr.s_addr = mcast_addr;
|
|
- ret = setsockopt(sock, IPPROTO_IP, (optname == IP_ADD_MEMBERSHIP) ?
|
|
- MCAST_JOIN_GROUP : MCAST_LEAVE_GROUP, (void *)&gr, sizeof(gr));
|
|
- if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE))
|
|
- {
|
|
- setsockopt(sock, IPPROTO_IP, MCAST_LEAVE_GROUP, (void *)&gr, sizeof(gr));
|
|
- ret = setsockopt(sock, IPPROTO_IP, MCAST_JOIN_GROUP, (void *)&gr, sizeof(gr));
|
|
- }
|
|
- return ret;
|
|
|
|
-#elif defined(HAVE_STRUCT_IP_MREQN_IMR_IFINDEX) && !defined(__FreeBSD__)
|
|
+#ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
|
|
+ /* This is better because it uses ifindex directly */
|
|
struct ip_mreqn mreqn;
|
|
int ret;
|
|
|
|
- assert(optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP);
|
|
- memset (&mreqn, 0, sizeof(mreqn));
|
|
-
|
|
- mreqn.imr_multiaddr.s_addr = mcast_addr;
|
|
- mreqn.imr_ifindex = ifindex;
|
|
-
|
|
- ret = setsockopt(sock, IPPROTO_IP, optname,
|
|
- (void *)&mreqn, sizeof(mreqn));
|
|
- if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE))
|
|
+ switch (optname)
|
|
{
|
|
- /* see above: handle possible problem when interface comes back up */
|
|
- char buf[1][INET_ADDRSTRLEN];
|
|
- zlog_info("setsockopt_ipv4_multicast attempting to drop and "
|
|
- "re-add (fd %d, mcast %s, ifindex %u)",
|
|
- sock,
|
|
- inet_ntop(AF_INET, &mreqn.imr_multiaddr,
|
|
- buf[0], sizeof(buf[0])), ifindex);
|
|
- setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
|
|
- (void *)&mreqn, sizeof(mreqn));
|
|
- ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
|
- (void *)&mreqn, sizeof(mreqn));
|
|
+ case IP_MULTICAST_IF:
|
|
+ case IP_ADD_MEMBERSHIP:
|
|
+ case IP_DROP_MEMBERSHIP:
|
|
+ memset (&mreqn, 0, sizeof(mreqn));
|
|
+
|
|
+ if (mcast_addr)
|
|
+ mreqn.imr_multiaddr.s_addr = mcast_addr;
|
|
+
|
|
+ if (ifindex)
|
|
+ mreqn.imr_ifindex = ifindex;
|
|
+ else
|
|
+ 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 */
|
|
+ char buf[2][INET_ADDRSTRLEN];
|
|
+ zlog_info("setsockopt_multicast_ipv4 attempting to drop and "
|
|
+ "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));
|
|
+ }
|
|
+ return ret;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ /* Can out and give an understandable error */
|
|
+ errno = EINVAL;
|
|
+ return -1;
|
|
+ break;
|
|
}
|
|
- return ret;
|
|
|
|
/* Example defines for another OS, boilerplate off other code in this
|
|
function, AND handle optname as per other sections for consistency !! */
|
|
/* #elif defined(BOGON_NIX) && EXAMPLE_VERSION_CODE > -100000 */
|
|
/* Add your favourite OS here! */
|
|
|
|
-#elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK) /* #if OS_TYPE */
|
|
+#else /* #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);
|
|
+#ifdef HAVE_BSD_STRUCT_IP_MREQ_HACK
|
|
+ if (ifindex)
|
|
+ m.s_addr = htonl(ifindex);
|
|
+ else
|
|
+#endif
|
|
+ m = if_addr;
|
|
|
|
- m.s_addr = htonl(ifindex);
|
|
-
|
|
- memset (&mreq, 0, sizeof(mreq));
|
|
- mreq.imr_multiaddr.s_addr = mcast_addr;
|
|
- mreq.imr_interface = m;
|
|
-
|
|
- ret = setsockopt (sock, IPPROTO_IP, optname, (void *)&mreq, sizeof(mreq));
|
|
- if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE))
|
|
+ switch (optname)
|
|
{
|
|
- /* see above: handle possible problem when interface comes back up */
|
|
- char buf[1][INET_ADDRSTRLEN];
|
|
- zlog_info("setsockopt_ipv4_multicast attempting to drop and "
|
|
- "re-add (fd %d, mcast %s, ifindex %u)",
|
|
- sock,
|
|
- inet_ntop(AF_INET, &mreq.imr_multiaddr,
|
|
- buf[0], sizeof(buf[0])), ifindex);
|
|
- setsockopt (sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
|
|
- (void *)&mreq, sizeof(mreq));
|
|
- ret = setsockopt (sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
|
- (void *)&mreq, sizeof(mreq));
|
|
- }
|
|
- return ret;
|
|
+ case IP_MULTICAST_IF:
|
|
+ return setsockopt (sock, IPPROTO_IP, optname, (void *)&m, sizeof(m));
|
|
+ break;
|
|
|
|
-#else
|
|
- #error "Unsupported multicast API"
|
|
+ case IP_ADD_MEMBERSHIP:
|
|
+ case IP_DROP_MEMBERSHIP:
|
|
+ memset (&mreq, 0, sizeof(mreq));
|
|
+ mreq.imr_multiaddr.s_addr = mcast_addr;
|
|
+ mreq.imr_interface = m;
|
|
+
|
|
+ ret = setsockopt (sock, IPPROTO_IP, optname, (void *)&mreq, sizeof(mreq));
|
|
+ if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE))
|
|
+ {
|
|
+ /* see above: handle possible problem when interface comes back up */
|
|
+ char buf[2][INET_ADDRSTRLEN];
|
|
+ zlog_info("setsockopt_multicast_ipv4 attempting to drop and "
|
|
+ "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, &mreq.imr_multiaddr,
|
|
+ buf[1], sizeof(buf[1])), ifindex);
|
|
+ setsockopt (sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
|
|
+ (void *)&mreq, sizeof(mreq));
|
|
+ ret = setsockopt (sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
|
+ (void *)&mreq, sizeof(mreq));
|
|
+ }
|
|
+ return ret;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ /* Can out and give an understandable error */
|
|
+ errno = EINVAL;
|
|
+ return -1;
|
|
+ break;
|
|
+ }
|
|
#endif /* #if OS_TYPE */
|
|
|
|
}
|
|
|
|
-/*
|
|
- * Set IP_MULTICAST_IF socket option in an OS-dependent manner.
|
|
- */
|
|
-int
|
|
-setsockopt_ipv4_multicast_if(int sock, ifindex_t ifindex)
|
|
-{
|
|
-
|
|
-#ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
|
|
- struct ip_mreqn mreqn;
|
|
- memset (&mreqn, 0, sizeof(mreqn));
|
|
-
|
|
- mreqn.imr_ifindex = ifindex;
|
|
- return setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&mreqn, sizeof(mreqn));
|
|
-
|
|
- /* Example defines for another OS, boilerplate off other code in this
|
|
- function */
|
|
- /* #elif defined(BOGON_NIX) && EXAMPLE_VERSION_CODE > -100000 */
|
|
- /* Add your favourite OS here! */
|
|
-#elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK)
|
|
- struct in_addr m;
|
|
-
|
|
- m.s_addr = htonl(ifindex);
|
|
-
|
|
- return setsockopt (sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&m, sizeof(m));
|
|
-#else
|
|
- #error "Unsupported multicast API"
|
|
-#endif
|
|
-}
|
|
-
|
|
static int
|
|
setsockopt_ipv4_ifindex (int sock, ifindex_t val)
|
|
{
|