summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpquerna <pquerna@13f79535-47bb-0310-9956-ffa450edef68>2005-01-10 02:50:57 +0000
committerpquerna <pquerna@13f79535-47bb-0310-9956-ffa450edef68>2005-01-10 02:50:57 +0000
commit824958c4e01f7d894b7e987e63023f14581bd158 (patch)
treea35a8c9f64ac33065170571764dea4c3d80f59a3
parent5e0190f08707d3dbabbadca9274532549a836494 (diff)
downloadlibapr-824958c4e01f7d894b7e987e63023f14581bd158.tar.gz
Add Support for Single Source Multicast.
Submitted By: Colm MacCarthaigh git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@124752 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--CHANGES2
-rw-r--r--include/apr_network_io.h14
-rw-r--r--network_io/unix/multicast.c134
3 files changed, 89 insertions, 61 deletions
diff --git a/CHANGES b/CHANGES
index 2e5481788..94e599d81 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,7 @@
Changes for APR 1.1.0
+ *) Add Support for Source-Specific Multicast. [Colm MacCarthaigh]
+
*) Add APR Multicast Functions [Paul Querna]
*) Add a build script to create a solaris package. [Graham Leggett]
diff --git a/include/apr_network_io.h b/include/apr_network_io.h
index 8721fa166..9df0ec29c 100644
--- a/include/apr_network_io.h
+++ b/include/apr_network_io.h
@@ -758,14 +758,13 @@ APR_DECLARE_INHERIT_UNSET(socket);
* @param join The address of the multicast group to join
* @param iface Address of the interface to use. If NULL is passed, the
* default multicast interface will be used. (OS Dependent)
- * @param ssm Single Source Multicast Address to accept transmissions from.
- * @remark Single Source Multicast is not currently implemented, and you must
- * pass NULL for the argument.
+ * @param source Source Address to accept transmissions from (non-NULL
+ * implies Source-Specific Multicast)
*/
APR_DECLARE(apr_status_t) apr_mcast_join(apr_socket_t *sock,
apr_sockaddr_t *join,
apr_sockaddr_t *iface,
- apr_sockaddr_t *ssm);
+ apr_sockaddr_t *source);
/**
* Leave a Multicast Group. All arguments must be the same as
@@ -774,14 +773,13 @@ APR_DECLARE(apr_status_t) apr_mcast_join(apr_socket_t *sock,
* @param leave The address of the multicast group to leave
* @param iface Address of the interface to use. If NULL is passed, the
* default multicast interface will be used. (OS Dependent)
- * @param ssm Single Source Multicast Address that transmissions came from.
- * @remark Single Source Multicast is not currently implemented, and you must
- * pass NULL for the argument.
+ * @param source Source Address to accept transmissions from (non-NULL
+ * implies Source-Specific Multicast)
*/
APR_DECLARE(apr_status_t) apr_mcast_leave(apr_socket_t *sock,
apr_sockaddr_t *leave,
apr_sockaddr_t *iface,
- apr_sockaddr_t *ssm);
+ apr_sockaddr_t *source);
/**
* Set the Multicast Time to Live (ttl) for a multicast transmission.
diff --git a/network_io/unix/multicast.c b/network_io/unix/multicast.c
index fc4e6b3ea..ba92bb9f4 100644
--- a/network_io/unix/multicast.c
+++ b/network_io/unix/multicast.c
@@ -25,7 +25,7 @@
#endif
/* Only UDP and Raw Sockets can be used for Multicast */
-static apr_status_t mcast_check_type(apr_socket_t* sock)
+static apr_status_t mcast_check_type(apr_socket_t *sock)
{
int type;
apr_status_t rv;
@@ -43,7 +43,7 @@ static apr_status_t mcast_check_type(apr_socket_t* sock)
}
}
-static void fill_mip_v4(struct ip_mreq *mip, apr_sockaddr_t *mcast,
+static void fill_mip_v4(struct ip_mreq *mip, apr_sockaddr_t *mcast,
apr_sockaddr_t *iface)
{
mip->imr_multiaddr = mcast->sa.sin.sin_addr;
@@ -56,7 +56,7 @@ static void fill_mip_v4(struct ip_mreq *mip, apr_sockaddr_t *mcast,
}
#if APR_HAVE_IPV6
-static unsigned int find_if_index(const apr_sockaddr_t *iface)
+static unsigned int find_if_index(const apr_sockaddr_t *iface)
{
unsigned int index = 0;
struct ifaddrs *ifp, *ifs;
@@ -75,12 +75,10 @@ static unsigned int find_if_index(const apr_sockaddr_t *iface)
}
for (ifp = ifs; ifp; ifp = ifp->ifa_next) {
- if (ifp->ifa_addr != NULL &&
- ifp->ifa_addr->sa_family == AF_INET6) {
- /* TODO: Is this correct? */
+ if (ifp->ifa_addr != NULL && ifp->ifa_addr->sa_family == AF_INET6) {
if (memcmp(&iface->sa.sin6.sin6_addr,
&ifp->ifa_addr->sa_data[0],
- sizeof(ifp->ifa_addr)) == 0) {
+ sizeof(iface->sa.sin6.sin6_addr)) == 0) {
index = if_nametoindex(ifp->ifa_name);
break;
}
@@ -92,7 +90,7 @@ static unsigned int find_if_index(const apr_sockaddr_t *iface)
return index;
}
-static void fill_mip_v6(struct ipv6_mreq *mip, const apr_sockaddr_t *mcast,
+static void fill_mip_v6(struct ipv6_mreq *mip, const apr_sockaddr_t *mcast,
const apr_sockaddr_t *iface)
{
memcpy(&mip->ipv6mr_multiaddr, mcast->ipaddr_ptr,
@@ -108,7 +106,7 @@ static void fill_mip_v6(struct ipv6_mreq *mip, const apr_sockaddr_t *mcast,
#endif
-static int sock_is_ipv4(apr_socket_t* sock)
+static int sock_is_ipv4(apr_socket_t *sock)
{
if (sock->local_addr->family == APR_INET)
return 1;
@@ -116,7 +114,7 @@ static int sock_is_ipv4(apr_socket_t* sock)
}
#if APR_HAVE_IPV6
-static int sock_is_ipv6(apr_socket_t* sock)
+static int sock_is_ipv6(apr_socket_t *sock)
{
if (sock->local_addr->family == APR_INET6)
return 1;
@@ -124,19 +122,19 @@ static int sock_is_ipv6(apr_socket_t* sock)
}
#endif
-static apr_status_t do_mcast(int type, apr_socket_t *sock,
+static apr_status_t do_mcast(int type, apr_socket_t *sock,
apr_sockaddr_t *mcast, apr_sockaddr_t *iface,
- apr_sockaddr_t *ssm)
+ apr_sockaddr_t *source)
{
struct ip_mreq mip4;
apr_status_t rv = APR_SUCCESS;
#if APR_HAVE_IPV6
struct ipv6_mreq mip6;
#endif
-
- /* We do not currently support Single Source Multicast. */
- if (ssm != NULL)
- return APR_ENOTIMPL;
+#if MCAST_JOIN_SOURCE_GROUP
+ struct group_source_req mip;
+ int ip_proto;
+#endif
rv = mcast_check_type(sock);
@@ -144,37 +142,68 @@ static apr_status_t do_mcast(int type, apr_socket_t *sock,
return rv;
}
- if (sock_is_ipv4(sock)) {
+ if (source != NULL) {
+#if MCAST_JOIN_SOURCE_GROUP
+ if (sock_is_ipv6(sock))
+ ip_proto = IPPROTO_IP;
+ else if (sock_is_ipv6(sock))
+ ip_proto = IPPROTO_IPV6;
+ else
+ return APR_ENOTIMPL;
- fill_mip_v4(&mip4, mcast, iface);
+ if (type == IP_ADD_MEMBERSHIP)
+ type = MCAST_JOIN_SOURCE_GROUP;
+ else if (type == IP_DROP_MEMBERSHIP)
+ type = MCAST_LEAVE_SOURCE_GROUP;
+ else
+ return APR_ENOTIMPL;
- if (setsockopt(sock->socketdes, IPPROTO_IP, type,
- (const void *)&mip4, sizeof(mip4)) == -1) {
+ mip.gsr_interface = find_if_index(iface);
+ memcpy(&mip.gsr_group, mcast->ipaddr_ptr, sizeof(mip.gsr_group));
+ memcpy(&mip.gsr_source, source->ipaddr_ptr, sizeof(mip.gsr_source));
+
+ if (setsockopt(sock->socketdes, ip_proto, type, (const void *) &mip,
+ sizeof(mip)) == -1) {
rv = errno;
}
+#else
+ /* We do not support Source-Specific Multicast. */
+ return APR_ENOTIMPL;
+#endif
}
-#if APR_HAVE_IPV6
- else if (sock_is_ipv6(sock)) {
- if (type == IP_ADD_MEMBERSHIP) {
- type = IPV6_JOIN_GROUP;
- }
- else if (type == IP_DROP_MEMBERSHIP) {
- type = IPV6_LEAVE_GROUP;
- }
- else {
- return APR_ENOTIMPL;
+ else {
+ if (sock_is_ipv4(sock)) {
+
+ fill_mip_v4(&mip4, mcast, iface);
+
+ if (setsockopt(sock->socketdes, IPPROTO_IP, type,
+ (const void *) &mip4, sizeof(mip4)) == -1) {
+ rv = errno;
+ }
}
+#if APR_HAVE_IPV6
+ else if (sock_is_ipv6(sock)) {
+ if (type == IP_ADD_MEMBERSHIP) {
+ type = IPV6_JOIN_GROUP;
+ }
+ else if (type == IP_DROP_MEMBERSHIP) {
+ type = IPV6_LEAVE_GROUP;
+ }
+ else {
+ return APR_ENOTIMPL;
+ }
- fill_mip_v6(&mip6, mcast, iface);
+ fill_mip_v6(&mip6, mcast, iface);
- if (setsockopt(sock->socketdes, IPPROTO_IPV6, type,
- &mip6, sizeof(mip6)) == -1) {
- rv = errno;
+ if (setsockopt(sock->socketdes, IPPROTO_IPV6, type,
+ &mip6, sizeof(mip6)) == -1) {
+ rv = errno;
+ }
}
- }
#endif
- else {
- rv = APR_ENOTIMPL;
+ else {
+ rv = APR_ENOTIMPL;
+ }
}
return rv;
}
@@ -183,7 +212,7 @@ static apr_status_t do_mcast_opt(int type, apr_socket_t *sock,
apr_byte_t value)
{
apr_status_t rv = APR_SUCCESS;
-
+
rv = mcast_check_type(sock);
if (rv != APR_SUCCESS) {
@@ -192,7 +221,7 @@ static apr_status_t do_mcast_opt(int type, apr_socket_t *sock,
if (sock_is_ipv4(sock)) {
if (setsockopt(sock->socketdes, IPPROTO_IP, type,
- (const void *)&value, sizeof(value)) == -1) {
+ (const void *) &value, sizeof(value)) == -1) {
rv = errno;
}
}
@@ -201,7 +230,7 @@ static apr_status_t do_mcast_opt(int type, apr_socket_t *sock,
unsigned int loopopt = value;
type = IPV6_MULTICAST_LOOP;
if (setsockopt(sock->socketdes, IPPROTO_IPV6, type,
- &loopopt, sizeof(loopopt)) == -1) {
+ &loopopt, sizeof(loopopt)) == -1) {
rv = errno;
}
}
@@ -213,8 +242,8 @@ static apr_status_t do_mcast_opt(int type, apr_socket_t *sock,
return APR_ENOTIMPL;
}
- if (setsockopt(sock->socketdes, IPPROTO_IPV6, type,
- &value, sizeof(value)) == -1) {
+ if (setsockopt(sock->socketdes, IPPROTO_IPV6, type,
+ &value, sizeof(value)) == -1) {
rv = errno;
}
}
@@ -229,10 +258,10 @@ static apr_status_t do_mcast_opt(int type, apr_socket_t *sock,
APR_DECLARE(apr_status_t) apr_mcast_join(apr_socket_t *sock,
apr_sockaddr_t *join,
apr_sockaddr_t *iface,
- apr_sockaddr_t *ssm)
+ apr_sockaddr_t *source)
{
#ifdef IP_ADD_MEMBERSHIP
- return do_mcast(IP_ADD_MEMBERSHIP, sock, join, iface, ssm);
+ return do_mcast(IP_ADD_MEMBERSHIP, sock, join, iface, source);
#else
return APR_ENOTIMPL;
#endif
@@ -241,17 +270,16 @@ APR_DECLARE(apr_status_t) apr_mcast_join(apr_socket_t *sock,
APR_DECLARE(apr_status_t) apr_mcast_leave(apr_socket_t *sock,
apr_sockaddr_t *leave,
apr_sockaddr_t *iface,
- apr_sockaddr_t *ssm)
+ apr_sockaddr_t *source)
{
#ifdef IP_DROP_MEMBERSHIP
- return do_mcast(IP_DROP_MEMBERSHIP, sock, leave, iface, ssm);
+ return do_mcast(IP_DROP_MEMBERSHIP, sock, leave, iface, source);
#else
return APR_ENOTIMPL;
#endif
}
-APR_DECLARE(apr_status_t) apr_mcast_hops(apr_socket_t *sock,
- apr_byte_t ttl)
+APR_DECLARE(apr_status_t) apr_mcast_hops(apr_socket_t *sock, apr_byte_t ttl)
{
#ifdef IP_MULTICAST_TTL
return do_mcast_opt(IP_MULTICAST_TTL, sock, ttl);
@@ -260,7 +288,7 @@ APR_DECLARE(apr_status_t) apr_mcast_hops(apr_socket_t *sock,
#endif
}
-APR_DECLARE(apr_status_t) apr_mcast_loopback(apr_socket_t *sock,
+APR_DECLARE(apr_status_t) apr_mcast_loopback(apr_socket_t *sock,
apr_byte_t opt)
{
#ifdef IP_MULTICAST_LOOP
@@ -278,16 +306,16 @@ APR_DECLARE(apr_status_t) apr_mcast_interface(apr_socket_t *sock,
if (sock_is_ipv4(sock)) {
if (setsockopt(sock->socketdes, IPPROTO_IP, IP_MULTICAST_IF,
- (const void *)&iface->sa.sin.sin_addr,
- sizeof(iface->sa.sin.sin_addr)) == -1) {
+ (const void *) &iface->sa.sin.sin_addr,
+ sizeof(iface->sa.sin.sin_addr)) == -1) {
rv = errno;
}
}
#if APR_HAVE_IPV6
else if (sock_is_ipv6(sock)) {
unsigned int idx = find_if_index(iface);
- if (setsockopt(sock->socketdes, IPPROTO_IPV6, IPV6_MULTICAST_IF,
- &idx, sizeof(idx)) == -1) {
+ if (setsockopt(sock->socketdes, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+ &idx, sizeof(idx)) == -1) {
rv = errno;
}
}