[PATCH] libosmocore[master]: socket.c: Add multicast related convenience functions

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Harald Welte gerrit-no-reply at lists.osmocom.org
Thu Jul 13 14:54:40 UTC 2017


Hello Jenkins Builder,

I'd like you to reexamine a change.  Please visit

    https://gerrit.osmocom.org/3238

to look at the new patch set (#2).

socket.c: Add multicast related convenience functions

Change-Id: Id703e7a7a1e065181a4c76c088b8dcc1b7fe15a2
---
M include/osmocom/core/socket.h
M src/socket.c
2 files changed, 141 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/38/3238/2

diff --git a/include/osmocom/core/socket.h b/include/osmocom/core/socket.h
index d2118ef..6db436a 100644
--- a/include/osmocom/core/socket.h
+++ b/include/osmocom/core/socket.h
@@ -8,6 +8,7 @@
  *  \file socket.h */
 
 #include <stdint.h>
+#include <stdbool.h>
 
 struct sockaddr;
 struct osmo_fd;
@@ -47,4 +48,9 @@
 
 char *osmo_sock_get_name(void *ctx, int fd);
 
+int osmo_sock_mcast_loop_set(int fd, bool enable);
+int osmo_sock_mcast_ttl_set(int fd, uint8_t ttl);
+int osmo_sock_mcast_all_set(int fd, bool enable);
+int osmo_sock_mcast_subscribe(int fd, const char *grp_addr);
+
 /*! @} */
diff --git a/src/socket.c b/src/socket.c
index 28d9b1c..d18f756 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -40,6 +40,7 @@
 #include <sys/un.h>
 
 #include <netinet/in.h>
+#include <arpa/inet.h>
 
 #include <stdio.h>
 #include <unistd.h>
@@ -614,6 +615,140 @@
 	return talloc_asprintf(ctx, "(r=NULL<->l=%s:%s)", hostbuf_l, portbuf_l);
 }
 
+static int sock_get_domain(int fd)
+{
+	int domain;
+#ifdef SO_DOMAIN
+	socklen_t dom_len = sizeof(domain);
+	int rc;
+
+	rc = getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &domain, &dom_len);
+	if (rc < 0)
+		return rc;
+#else
+	/* This of course sucks, but what shall we do on OSs like
+	 * FreeBSD that don't seem to expose a method by which one can
+	 * learn the address family of a socket? */
+	domain = AF_INET;
+#endif
+	return domain;
+}
+
+
+/*! Activate or de-activate local loop-back of transmitted multicast packets
+ *  \param[in] fd file descriptor of related socket
+ *  \param[in] enable Enable (true) or disable (false) loop-back
+ *  \returns 0 on success; negative otherwise */
+int osmo_sock_mcast_loop_set(int fd, bool enable)
+{
+	int domain, loop = 0;
+
+	if (enable)
+		loop = 1;
+
+	domain = sock_get_domain(fd);
+	if (domain < 0)
+		return domain;
+
+	switch (domain) {
+	case AF_INET:
+		return setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));
+	case AF_INET6:
+		return setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop, sizeof(loop));
+	default:
+		return -EINVAL;
+	}
+}
+
+/*! Set the TTL of outbound multicast packets
+ *  \param[in] fd file descriptor of related socket
+ *  \param[in] ttl TTL of to-be-sent multicast packets
+ *  \returns 0 on success; negative otherwise */
+int osmo_sock_mcast_ttl_set(int fd,  uint8_t ttl)
+{
+	int domain, ttli = ttl;
+
+	domain = sock_get_domain(fd);
+	if (domain < 0)
+		return domain;
+
+	switch (domain) {
+	case AF_INET:
+		return setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttli, sizeof(ttli));
+	case AF_INET6:
+		return setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttli, sizeof(ttli));
+	default:
+		return -EINVAL;
+	}
+}
+
+/*! Enable/disable receiving all multicast packets, even for non-subscribed groups
+ *  \param[in] fd file descriptor of related socket
+ *  \param[in] enable Enable or Disable receiving of all packets
+ *  \returns 0 on success; negative otherwise */
+int osmo_sock_mcast_all_set(int fd, bool enable)
+{
+	int domain, all = 0;
+
+	if (enable)
+		all = 1;
+
+	domain = sock_get_domain(fd);
+	if (domain < 0)
+		return domain;
+
+	switch (domain) {
+	case AF_INET:
+#ifdef IP_MULTICAST_ALL
+		return setsockopt(fd, IPPROTO_IP, IP_MULTICAST_ALL, &all, sizeof(all));
+#endif
+	case AF_INET6:
+		/* there seems no equivalent ?!? */
+	default:
+		return -EINVAL;
+	}
+}
+
+/* FreeBSD calls the socket option differently */
+#if !defined(IPV6_ADD_MEMBERSHIP) && defined(IPV6_JOIN_GROUP)
+#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
+#endif
+
+/*! Subscribe to the given IP multicast group
+ *  \param[in] fd file descriptor of related scoket
+ *  \param[in] grp_addr ASCII representation of the multicast group address
+ *  \returns 0 on success; negative otherwise */
+int osmo_sock_mcast_subscribe(int fd, const char *grp_addr)
+{
+	int rc, domain;
+	struct ip_mreq mreq;
+	struct ipv6_mreq mreq6;
+	struct in6_addr i6a;
+
+	domain = sock_get_domain(fd);
+	if (domain < 0)
+		return domain;
+
+	switch (domain) {
+	case AF_INET:
+		memset(&mreq, 0, sizeof(mreq));
+		mreq.imr_multiaddr.s_addr = inet_addr(grp_addr);
+		mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+		return setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
+#ifdef IPV6_ADD_MEMBERSHIP
+	case AF_INET6:
+		memset(&mreq6, 0, sizeof(mreq6));
+		rc = inet_pton(AF_INET6, grp_addr, (void *)&i6a);
+		if (rc < 0)
+			return -EINVAL;
+		mreq6.ipv6mr_multiaddr = i6a;
+		return setsockopt(fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6));
+#endif
+	default:
+		return -EINVAL;
+	}
+}
+
 #endif /* HAVE_SYS_SOCKET_H */
 
 /*! @} */

-- 
To view, visit https://gerrit.osmocom.org/3238
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: Id703e7a7a1e065181a4c76c088b8dcc1b7fe15a2
Gerrit-PatchSet: 2
Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder



More information about the gerrit-log mailing list