New port: net/mcjoin: Simple multicast testing application for UNIX

mcjoin is a very simple and easy-to-use tool to test IPv4 and IPv6
multicast. It features:

    *   an optional multicast generator (server)
    *   an end device that can act as a data sink (client)
    *   supports joining one or more groups:
        *   ASM (*,G) support
        *   SSM (S,G) support
    *   IPv4
    *   IPv6

WWW: https://github.com/troglobit/mcjoin

PR:		243787
Submitted by:	John W. O'Brien <john@saltant.com>
This commit is contained in:
Kurt Jaeger 2020-03-01 08:34:04 +00:00
parent ca43454075
commit 53cf56ead2
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/head/; revision=527541
6 changed files with 202 additions and 0 deletions

View file

@ -435,6 +435,7 @@
SUBDIR += mailcommon
SUBDIR += mailimporter
SUBDIR += malo-firmware-kmod
SUBDIR += mcjoin
SUBDIR += mdns-repeater
SUBDIR += measurement-kit
SUBDIR += mediastreamer

20
net/mcjoin/Makefile Normal file
View file

@ -0,0 +1,20 @@
# $FreeBSD$
PORTNAME= mcjoin
DISTVERSIONPREFIX= v
DISTVERSION= 2.4
CATEGORIES= net
MAINTAINER= john@saltant.com
COMMENT= Simple multicast testing application for UNIX
LICENSE= ISCL
LICENSE_FILE= ${WRKSRC}/LICENSE
USES= autoreconf
GNU_CONFIGURE= yes
USE_GITHUB= yes
GH_ACCOUNT= troglobit
.include <bsd.port.mk>

3
net/mcjoin/distinfo Normal file
View file

@ -0,0 +1,3 @@
TIMESTAMP = 1580591567
SHA256 (troglobit-mcjoin-v2.4_GH0.tar.gz) = 8374018bba71621f48e67ce37f25ba095ce7ff247d67e46ac6171a9e68b30cc7
SIZE (troglobit-mcjoin-v2.4_GH0.tar.gz) = 16108

View file

@ -0,0 +1,163 @@
commit 27657e27db1704fd258139a57ad3312003a6cef9
Author: Ryan Libby <rlibby@FreeBSD.org>
Date: Sun Nov 24 21:33:49 2019 -0800
Build and run on FreeBSD
An assortment of small changes to build and run on FreeBSD. FreeBSD:
- Doesn't have IP_PKTINFO, but does have IP_RECVDSTADDR.
- Doesn't have IP_MULTICAST_ALL (and doesn't need to disable it).
- Is sensitive about the claimed size of the sockaddr, and has
sockaddrs with builtin len fields.
- Doesn't export s6_addr32.
--- configure.ac.orig 2019-04-04 07:57:50 UTC
+++ configure.ac
@@ -10,4 +10,9 @@ AC_PROG_INSTALL
AC_HEADER_STDC
+AC_CHECK_MEMBERS([struct sockaddr_storage.ss_len], , ,
+[
+#include <sys/socket.h>
+])
+
AC_OUTPUT
--- mcjoin.c.orig 2019-04-04 07:57:50 UTC
+++ mcjoin.c
@@ -123,6 +123,18 @@ static const char *convert_address(inet_addr_t *ss, ch
return inet_ntop(AF_INET, &sin->sin_addr, buf, len);
}
+static socklen_t ss_get_len(const struct sockaddr_storage *ss)
+{
+
+#ifdef AF_INET6
+ if (ss->ss_family == AF_INET6)
+ return sizeof(struct sockaddr_in6);
+#endif
+ if (ss->ss_family == AF_INET)
+ return sizeof(struct sockaddr_in);
+ return 0;
+}
+
static int alloc_socket(inet_addr_t group)
{
int sd, val, proto;
@@ -148,15 +160,22 @@ static int alloc_socket(inet_addr_t group)
if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)))
ERROR("Failed enabling SO_REUSEADDR: %s", strerror(errno));
+#if defined(IP_PKTINFO) || !defined(IP_RECVDSTADDR)
if (setsockopt(sd, SOL_IP, IP_PKTINFO, &val, sizeof(val)))
ERROR("Failed enabling IP_PKTINFO: %s", strerror(errno));
+#elif defined(IP_RECVDSTADDR)
+ if (setsockopt(sd, IPPROTO_IP, IP_RECVDSTADDR, &val, sizeof(val)))
+ ERROR("Failed enabling IP_RECVDSTADDR: %s", strerror(errno));
+#endif
val = 0;
+#ifdef IP_MULTICAST_ALL
if (setsockopt(sd, proto, IP_MULTICAST_ALL, &val, sizeof(val)))
ERROR("Failed disabling IP_MULTICAST_ALL: %s", strerror(errno));
+#endif
- if (bind(sd, (struct sockaddr *)&group, sizeof(group))) {
- ERROR("Faild binding to socket: %s", strerror(errno));
+ if (bind(sd, (struct sockaddr *)&group, ss_get_len(&group))) {
+ ERROR("Failed binding to socket: %s", strerror(errno));
close(sd);
return -1;
}
@@ -266,7 +285,7 @@ static void send_mcast(int signo)
for (i = 0; i < group_num; i++) {
struct sockaddr *dest = (struct sockaddr *)&groups[i].grp;
- socklen_t len = sizeof(groups[i].grp);
+ socklen_t len = ss_get_len(&groups[i].grp);
snprintf(buf, sizeof(buf), "%s%u, MC group %s ... count: %u", MAGIC_KEY, getpid(), groups[i].group, counter++);
DEBUG("Sending packet on signal %d, msg: %s", signo, buf);
@@ -275,15 +294,21 @@ static void send_mcast(int signo)
}
}
-struct in_pktinfo *find_pktinfo(struct msghdr *msgh)
+struct in_addr *find_dstaddr(struct msghdr *msgh)
{
struct cmsghdr *cmsg;
for (cmsg = CMSG_FIRSTHDR(msgh); cmsg; cmsg = CMSG_NXTHDR(msgh, cmsg)) {
- if (cmsg->cmsg_level != SOL_IP || cmsg->cmsg_type != IP_PKTINFO)
- continue;
-
- return (struct in_pktinfo *)CMSG_DATA(cmsg);
+#if defined(IP_PKTINFO) || !defined(IP_RECVDSTADDR)
+ if (cmsg->cmsg_level == IPPROTO_IP &&
+ cmsg->cmsg_type == IP_PKTINFO)
+ return &((struct in_pktinfo *)CMSG_DATA(cmsg))->
+ ipi_addr;
+#elif defined(IP_RECVDSTADDR)
+ if (cmsg->cmsg_level == IPPROTO_IP &&
+ cmsg->cmsg_type == IP_RECVDSTADDR)
+ return (struct in_addr *)CMSG_DATA(cmsg);
+#endif
}
return NULL;
@@ -314,7 +339,7 @@ static void progress(void)
static ssize_t recv_mcast(int id)
{
struct sockaddr_storage src;
- struct in_pktinfo *ipi;
+ struct in_addr *dstaddr;
struct msghdr msgh;
struct iovec iov[1];
ssize_t bytes;
@@ -336,8 +361,8 @@ static ssize_t recv_mcast(int id)
if (bytes < 0)
return -1;
- ipi = find_pktinfo(&msgh);
- if (ipi) {
+ dstaddr = find_dstaddr(&msgh);
+ if (dstaddr) {
char *ptr;
int pid = 0;
@@ -348,7 +373,7 @@ static ssize_t recv_mcast(int id)
DEBUG("Count %5zu, our PID %d, sender PID %d, group %s msg: %s", groups[id].count, getpid(), pid, groups[id].group, buf);
if (pid != getpid()) {
- char *dst = inet_ntoa(ipi->ipi_addr);
+ char *dst = inet_ntoa(*dstaddr);
if (strcmp(dst, groups[id].group)) {
ERROR("Packet for group %s received on wrong socket, expected group %s.", dst, groups[id].group);
@@ -658,9 +683,11 @@ int main(int argc, char *argv[])
/* Next group ... */
#ifdef AF_INET6
if (strchr(group, ':')) {
- step = ntohl(sin6->sin6_addr.s6_addr32[3]);
- step++;
- sin6->sin6_addr.s6_addr32[3] = htonl(step);
+ memcpy(&step, &sin6->sin6_addr.s6_addr[12],
+ sizeof(step));
+ step = htonl(ntohl(step) + 1);
+ memcpy(&sin6->sin6_addr.s6_addr[12], &step,
+ sizeof(step));
len = sizeof(*sin6);
} else
#endif
@@ -706,6 +733,11 @@ int main(int argc, char *argv[])
src->sin_port = htons(port);
}
}
+#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
+ groups[i].grp.ss_len = ss_get_len(&groups[i].grp);
+ if (groups[i].source)
+ groups[i].src.ss_len = ss_get_len(&groups[i].src);
+#endif
}
/*

12
net/mcjoin/pkg-descr Normal file
View file

@ -0,0 +1,12 @@
mcjoin is a very simple and easy-to-use tool to test IPv4 and IPv6
multicast. It features:
* an optional multicast generator (server)
* an end device that can act as a data sink (client)
* supports joining one or more groups:
* ASM (*,G) support
* SSM (S,G) support
* IPv4
* IPv6
WWW: https://github.com/troglobit/mcjoin

3
net/mcjoin/pkg-plist Normal file
View file

@ -0,0 +1,3 @@
bin/mcjoin
%%DOCSDIR%%/README.md
man/man1/mcjoin.1.gz