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
Review at https://gerrit.osmocom.org/3238
socket.c: Add multicast related convenience functions
Change-Id: Id703e7a7a1e065181a4c76c088b8dcc1b7fe15a2
---
M include/osmocom/core/socket.h
M src/socket.c
2 files changed, 117 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/38/3238/1
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..688fcb3 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,116 @@
return talloc_asprintf(ctx, "(r=NULL<->l=%s:%s)", hostbuf_l, portbuf_l);
}
+/*! 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 rc, domain, loop = 0;
+ socklen_t dom_len = sizeof(domain);
+
+ if (enable)
+ loop = 1;
+
+ rc = getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &domain, &dom_len);
+ if (rc < 0)
+ return rc;
+
+ 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 rc, domain, ttli = ttl;
+ socklen_t dom_len = sizeof(domain);
+
+ rc = getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &domain, &dom_len);
+ if (rc < 0)
+ return rc;
+
+ 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 rc, domain, all = 0;
+ socklen_t dom_len = sizeof(domain);
+
+ if (enable)
+ all = 1;
+
+ rc = getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &domain, &dom_len);
+ if (rc < 0)
+ return rc;
+
+ switch (domain) {
+ case AF_INET:
+ return setsockopt(fd, IPPROTO_IP, IP_MULTICAST_ALL, &all, sizeof(all));
+ case AF_INET6:
+ /* there seems no equivalent ?!? */
+ default:
+ return -EINVAL;
+ }
+}
+
+
+/*! 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;
+ socklen_t dom_len = sizeof(domain);
+ struct ip_mreq mreq;
+ struct ipv6_mreq mreq6;
+ struct in6_addr i6a;
+
+ rc = getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &domain, &dom_len);
+ if (rc < 0)
+ return rc;
+
+ 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));
+ 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));
+ 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: newchange
Gerrit-Change-Id: Id703e7a7a1e065181a4c76c088b8dcc1b7fe15a2
Gerrit-PatchSet: 1
Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <laforge at gnumonks.org>