include $(TOPDIR)/rules.mk
PKG_NAME:=net-mtools
-PKG_VERSION:=2.3
+PKG_VERSION:=3.1
PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=https://github.com/troglobit/mtools
-PKG_SOURCE_VERSION:=db665a4303c38cee908eba4dac50873c3f1d899c
-PKG_MIRROR_HASH:=a554990482054b26a207dc9eb6ed5685eb228773cc07f45fb2d37fca59122ca0
+PKG_SOURCE_VERSION:=bbf932d7d98d8e9651338355db435babded9d11e
+PKG_MIRROR_HASH:=98a3620566641849b556cdaafe17f2f7969424466e8c3ba0f4591e8595b7e2f2
include $(INCLUDE_DIR)/package.mk
+++ /dev/null
-From 0cfc04eac370ee33118e17a298d4739c94cacc73 Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Tue, 19 Apr 2022 12:28:03 +0300
-Subject: [PATCH 1/6] mreceive: refactor multicast joining to separate function
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- mreceive.c | 33 ++++++++++++++++++---------------
- 1 file changed, 18 insertions(+), 15 deletions(-)
-
---- a/mreceive.c
-+++ b/mreceive.c
-@@ -61,12 +61,27 @@ Usage: mreceive [-g GROUP] [-p PORT] [-i
- -h Print the command usage.\n\n", VERSION);
- }
-
-+static void igmp_join(int s, in_addr_t multiaddr, in_addr_t interface)
-+{
-+ struct ip_mreq mreq;
-+ int ret;
-+
-+ mreq.imr_multiaddr.s_addr = multiaddr;
-+ mreq.imr_interface.s_addr = interface;
-+
-+ ret = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP,
-+ (char *)&mreq, sizeof(mreq));
-+ if (ret == SOCKET_ERROR) {
-+ printf("setsockopt() IP_ADD_MEMBERSHIP failed.\n");
-+ exit(1);
-+ }
-+}
-+
- int main(int argc, char *argv[])
- {
- struct sockaddr_in stLocal, stFrom;
- unsigned char achIn[BUFSIZE];
- int s, i;
-- struct ip_mreq stMreq;
- int iTmp, iRet;
- int ipnum = 0;
- int ii;
-@@ -153,22 +168,10 @@ int main(int argc, char *argv[])
-
- /* join the multicast group. */
- if (!ipnum) { /* single interface */
-- stMreq.imr_multiaddr.s_addr = inet_addr(TEST_ADDR);
-- stMreq.imr_interface.s_addr = INADDR_ANY;
-- iRet = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&stMreq, sizeof(stMreq));
-- if (iRet == SOCKET_ERROR) {
-- printf("setsockopt() IP_ADD_MEMBERSHIP failed.\n");
-- exit(1);
-- }
-+ igmp_join(s, inet_addr(TEST_ADDR), INADDR_ANY);
- } else {
- for (i = 0; i < ipnum; i++) {
-- stMreq.imr_multiaddr.s_addr = inet_addr(TEST_ADDR);
-- stMreq.imr_interface.s_addr = IP[i];
-- iRet = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&stMreq, sizeof(stMreq));
-- if (iRet == SOCKET_ERROR) {
-- printf("setsockopt() IP_ADD_MEMBERSHIP failed.\n");
-- exit(1);
-- }
-+ igmp_join(s, inet_addr(TEST_ADDR), IP[i]);
- }
- }
-
+++ /dev/null
-From 65af96e0907ba9367aab9c1534b11c7f674c1e6a Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Tue, 19 Apr 2022 13:29:07 +0300
-Subject: [PATCH 2/6] mreceive: join IGMP group by interface
-
-mreceive uses the old-style struct ip_mreq for IP_ADD_MEMBERSHIP, which
-takes the source address of the interface wishing to join.
-
-Since the IPV6_ADD_MEMBERSHIP variant only takes a struct ipv6_mreq
-which contains the ifindex and not the source address, we need to add
-support for that.
-
-In preparation for IPv6 support, add logic to join an IGMP group either
-by source address or by interface name, whichever is specified.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- mreceive.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
- 1 file changed, 46 insertions(+), 5 deletions(-)
-
---- a/mreceive.c
-+++ b/mreceive.c
-@@ -23,6 +23,7 @@
- #include <string.h>
- #include <sys/types.h>
- #include <sys/socket.h>
-+#include <net/if.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <sys/time.h>
-@@ -61,7 +62,7 @@ Usage: mreceive [-g GROUP] [-p PORT] [-i
- -h Print the command usage.\n\n", VERSION);
- }
-
--static void igmp_join(int s, in_addr_t multiaddr, in_addr_t interface)
-+static void igmp_join_by_saddr(int s, in_addr_t multiaddr, in_addr_t interface)
- {
- struct ip_mreq mreq;
- int ret;
-@@ -77,10 +78,34 @@ static void igmp_join(int s, in_addr_t m
- }
- }
-
-+static void igmp_join_by_if_name(int s, in_addr_t multicast,
-+ const char *if_name)
-+{
-+ struct ip_mreqn mreq = {};
-+ int if_index;
-+ int ret;
-+
-+ if_index = if_nametoindex(if_name);
-+ if (!if_index) {
-+ perror("if_nametoindex");
-+ exit(1);
-+ }
-+
-+ mreq.imr_multiaddr.s_addr = multicast;
-+ mreq.imr_ifindex = if_index;
-+
-+ ret = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
-+ if (ret) {
-+ perror("setsockopt() IP_ADD_MEMBERSHIP");
-+ exit(1);
-+ }
-+}
-+
- int main(int argc, char *argv[])
- {
- struct sockaddr_in stLocal, stFrom;
- unsigned char achIn[BUFSIZE];
-+ const char *if_name;
- int s, i;
- int iTmp, iRet;
- int ipnum = 0;
-@@ -131,6 +156,17 @@ int main(int argc, char *argv[])
- ii++;
- ipnum++;
- }
-+ } else if (strcmp(argv[ii], "-I") == 0) {
-+ ii++;
-+ if (ii < argc) {
-+ if (if_name) {
-+ printf("Single interface expected\n");
-+ exit(1);
-+ }
-+
-+ if_name = argv[ii];
-+ ii++;
-+ }
- } else if (strcmp(argv[ii], "-n") == 0) {
- ii++;
- NUM = 1;
-@@ -167,11 +203,16 @@ int main(int argc, char *argv[])
- }
-
- /* join the multicast group. */
-- if (!ipnum) { /* single interface */
-- igmp_join(s, inet_addr(TEST_ADDR), INADDR_ANY);
-+ if (if_name) {
-+ igmp_join_by_if_name(s, inet_addr(TEST_ADDR), if_name);
- } else {
-- for (i = 0; i < ipnum; i++) {
-- igmp_join(s, inet_addr(TEST_ADDR), IP[i]);
-+ if (!ipnum) { /* single interface */
-+ igmp_join_by_saddr(s, inet_addr(TEST_ADDR), INADDR_ANY);
-+ } else {
-+ for (i = 0; i < ipnum; i++) {
-+ igmp_join_by_saddr(s, inet_addr(TEST_ADDR),
-+ IP[i]);
-+ }
- }
- }
-
+++ /dev/null
-From cc7f68045e5f3cfc6c932996af784ab319951426 Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Tue, 19 Apr 2022 13:29:20 +0300
-Subject: [PATCH 3/6] mreceive: support IPv6
-
-Extend the mreceive program with a generalization of sockets,
-addresses and socket options that covers both IPv4 and IPv6.
-
-Most of the lower-level implementation is moved to common.c and exported
-through common.h such that it can be reused by msend at a later time.
-
-The makefile rule to link object files into executables is updated to
-look at all specified objects rather than just the first, by using $^
-instead of $<. Otherwise, common.o would be ignored when linking
-mreceive.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- Makefile | 8 +-
- common.c | 261 +++++++++++++++++++++++++++++++++++++++++++++++++++++
- common.h | 36 ++++++++
- mreceive.c | 142 ++++++++++-------------------
- 4 files changed, 349 insertions(+), 98 deletions(-)
- create mode 100644 common.c
- create mode 100644 common.h
-
---- a/Makefile
-+++ b/Makefile
-@@ -20,8 +20,8 @@ mandir = $(prefix)/share/man/man8
- # ttcp is currently not part of the distribution because its not tested
- # yet. Please test and let me know at GitHub so I can include it! :)
- EXEC := msend mreceive
--OBJS := $(EXEC:=.o)
--DEPS := $(EXEC:=.d)
-+OBJS := msend.o mreceive.o common.o
-+DEPS := msend.d mreceive.d common.d
- MANS = $(addsuffix .8,$(EXEC))
- DISTFILES = README.md LICENSE.md
-
-@@ -33,10 +33,10 @@ all: $(EXEC)
-
- .o:
- @printf " LINK $@\n"
-- @$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-Map,$@.map -o $@ $< $(LDLIBS$(LDLIBS-$(@)))
-+ @$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-Map,$@.map -o $@ $^ $(LDLIBS$(LDLIBS-$(@)))
-
- msend: msend.o
--mreceive: mreceive.o
-+mreceive: mreceive.o common.o
- ttcp: ttcp.o
-
- install: $(EXEC)
---- /dev/null
-+++ b/common.c
-@@ -0,0 +1,261 @@
-+/*
-+ * common.c -- Common functions for mreceive.c and msend.c
-+ */
-+#include <arpa/inet.h>
-+#include <net/if.h>
-+#include <stdio.h>
-+#include <string.h>
-+#include <unistd.h>
-+
-+#include "common.h"
-+
-+int ip_address_parse(const char *string, struct ip_address *ip)
-+{
-+ int ret;
-+
-+ ret = inet_pton(AF_INET6, string, &ip->addr6);
-+ if (ret > 0) {
-+ ip->family = AF_INET6;
-+ } else {
-+ ret = inet_pton(AF_INET, string, &ip->addr);
-+ if (ret > 0) {
-+ ip->family = AF_INET;
-+ } else {
-+ fprintf(stderr, "IP address %s not in known format\n",
-+ string);
-+ return -1;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+int socket_create(struct sock *s, int family, int port)
-+{
-+ struct sockaddr *serv_addr;
-+ int sockopt = 1;
-+ int fd, ret;
-+
-+ memset(s, 0, sizeof(*s));
-+
-+ if (family == AF_INET) {
-+ serv_addr = (struct sockaddr *)&s->udp4;
-+ s->udp4.sin_addr.s_addr = htonl(INADDR_ANY);
-+ s->udp4.sin_port = htons(port);
-+ s->udp4.sin_family = AF_INET;
-+ s->addr_size = sizeof(struct sockaddr_in);
-+ } else {
-+ serv_addr = (struct sockaddr *)&s->udp6;
-+ s->udp6.sin6_addr = in6addr_any;
-+ s->udp6.sin6_port = htons(port);
-+ s->udp6.sin6_family = AF_INET6;
-+ s->addr_size = sizeof(struct sockaddr_in6);
-+ }
-+
-+ fd = socket(family, SOCK_DGRAM, 0);
-+ if (fd < 0) {
-+ perror("socket");
-+ return fd;
-+ }
-+
-+ /* avoid EADDRINUSE error on bind() */
-+ ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(int));
-+ if (ret) {
-+ perror("setsockopt() SO_REUSEADDR");
-+ close(fd);
-+ return ret;
-+ }
-+
-+ ret = bind(fd, serv_addr, s->addr_size);
-+ if (ret) {
-+ perror("bind");
-+ close(fd);
-+ return ret;
-+ }
-+
-+ s->fd = fd;
-+
-+ return 0;
-+}
-+
-+static int igmp_join_by_saddr(struct sock *s, const struct ip_address *mc,
-+ struct ip_address *saddr)
-+{
-+ struct ip_mreq mreq = {};
-+ int fd = s->fd;
-+ int off = 0;
-+ int ret;
-+
-+ memcpy(&mreq.imr_multiaddr, &mc->addr, sizeof(struct in_addr));
-+ memcpy(&mreq.imr_interface.s_addr, &saddr->addr,
-+ sizeof(struct in_addr));
-+
-+ ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
-+ if (ret) {
-+ perror("setsockopt() IP_ADD_MEMBERSHIP");
-+ return -1;
-+ }
-+
-+ ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &off, sizeof(int));
-+ if (ret) {
-+ perror("setsockopt() IP_MULTICAST_LOOP");
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+static int igmp_join_by_if_name(struct sock *s, const struct ip_address *mc,
-+ const char *if_name)
-+{
-+ struct ip_mreqn mreq = {};
-+ int fd = s->fd;
-+ int if_index;
-+ int off = 0;
-+ int ret;
-+
-+ if_index = if_nametoindex(if_name);
-+ if (!if_index) {
-+ perror("if_nametoindex");
-+ return -1;
-+ }
-+
-+ memcpy(&mreq.imr_multiaddr, &mc->addr, sizeof(struct in_addr));
-+ mreq.imr_ifindex = if_index;
-+
-+ ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
-+ if (ret) {
-+ perror("setsockopt() IP_ADD_MEMBERSHIP");
-+ return -1;
-+ }
-+
-+ ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &off, sizeof(int));
-+ if (ret) {
-+ perror("setsockopt() IP_MULTICAST_LOOP");
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+static int mld_join(struct sock *s, const struct ip_address *mc,
-+ const char *if_name)
-+{
-+ struct ipv6_mreq mreq = {};
-+ int if_index, off = 0;
-+ int fd = s->fd;
-+ int ret;
-+
-+ if_index = if_nametoindex(if_name);
-+ if (!if_index) {
-+ perror("if_nametoindex");
-+ return -1;
-+ }
-+
-+ memcpy(&mreq.ipv6mr_multiaddr, &mc->addr6, sizeof(struct in6_addr));
-+ mreq.ipv6mr_interface = if_index;
-+ ret = setsockopt(fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq,
-+ sizeof(mreq));
-+ if (ret) {
-+ perror("setsockopt IPV6_ADD_MEMBERSHIP");
-+ return -1;
-+ }
-+
-+ ret = setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off,
-+ sizeof(int));
-+ if (ret) {
-+ perror("setsockopt IPV6_MULTICAST_LOOP");
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+int mc_join(struct sock *s, const struct ip_address *mc, const char *if_name,
-+ int num_saddrs, struct ip_address *saddrs)
-+{
-+ int i, ret;
-+
-+ if (if_name) {
-+ switch (mc->family) {
-+ case AF_INET:
-+ return igmp_join_by_if_name(s, mc, if_name);
-+ case AF_INET6:
-+ return mld_join(s, mc, if_name);
-+ default:
-+ return -1;
-+ }
-+ }
-+
-+ if (!num_saddrs) { /* single interface */
-+ struct ip_address saddr = {
-+ .family = AF_INET,
-+ .addr.s_addr = INADDR_ANY,
-+ };
-+
-+ return igmp_join_by_saddr(s, mc, &saddr);
-+ }
-+
-+ for (i = 0; i < num_saddrs; i++) {
-+ ret = igmp_join_by_saddr(s, mc, &saddrs[i]);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
-+static int igmp_set_ttl(int fd, int ttl)
-+{
-+ int ret;
-+
-+ ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(int));
-+ if (ret)
-+ perror("setsockopt() IP_MULTICAST_TTL");
-+
-+ return ret;
-+}
-+
-+static int mld_set_hop_limit(int fd, int limit)
-+{
-+ int ret;
-+
-+ ret = setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &limit,
-+ sizeof(int));
-+ if (ret)
-+ perror("setsockopt() IPV6_MULTICAST_HOPS");
-+
-+ return ret;
-+}
-+
-+int mc_set_hop_limit(struct sock *s, int limit)
-+{
-+ switch (s->addr_size) {
-+ case sizeof(struct sockaddr_in):
-+ return igmp_set_ttl(s->fd, limit);
-+ case sizeof(struct sockaddr_in6):
-+ return mld_set_hop_limit(s->fd, limit);
-+ default:
-+ return -1;
-+ }
-+}
-+
-+int mc_recv(struct sock *s, void *buf, size_t len, struct sock *from)
-+{
-+ from->addr_size = sizeof(struct sockaddr_in6);
-+
-+ return recvfrom(s->fd, buf, len, 0, (struct sockaddr *)&(from->udp6),
-+ &from->addr_size);
-+}
-+
-+int socket_get_port(const struct sock *s)
-+{
-+ switch (s->addr_size) {
-+ case sizeof(struct sockaddr_in):
-+ return ntohs(s->udp4.sin_port);
-+ case sizeof(struct sockaddr_in6):
-+ return ntohs(s->udp6.sin6_port);
-+ default:
-+ return 0;
-+ }
-+}
---- /dev/null
-+++ b/common.h
-@@ -0,0 +1,36 @@
-+/*
-+ * common.h -- Common header for mreceive.c and msend.c
-+ */
-+#ifndef _COMMON_H
-+#define _COMMON_H
-+
-+#include <netinet/in.h>
-+#include <netinet/ip.h>
-+#include <netinet/ip6.h>
-+
-+struct ip_address {
-+ int family;
-+ union {
-+ struct in_addr addr;
-+ struct in6_addr addr6;
-+ };
-+};
-+
-+struct sock {
-+ socklen_t addr_size;
-+ union {
-+ struct sockaddr_in udp4;
-+ struct sockaddr_in6 udp6;
-+ };
-+ int fd;
-+};
-+
-+int ip_address_parse(const char *string, struct ip_address *ip);
-+int socket_create(struct sock *s, int family, int port);
-+int mc_join(struct sock *s, const struct ip_address *mc, const char *if_name,
-+ int num_saddrs, struct ip_address *saddrs);
-+int mc_set_hop_limit(struct sock *s, int limit);
-+int mc_recv(struct sock *s, void *buf, size_t len, struct sock *from);
-+int socket_get_port(const struct sock *s);
-+
-+#endif
---- a/mreceive.c
-+++ b/mreceive.c
-@@ -28,6 +28,8 @@
- #include <arpa/inet.h>
- #include <sys/time.h>
-
-+#include "common.h"
-+
- #define TRUE 1
- #define FALSE 0
- #ifndef INVALID_SOCKET
-@@ -43,7 +45,7 @@
-
- char *TEST_ADDR = "224.1.1.1";
- int TEST_PORT = 4444;
--unsigned long IP[MAXIP];
-+struct ip_address IP[MAXIP];
- int NUM = 0;
-
- void printHelp(void)
-@@ -62,52 +64,12 @@ Usage: mreceive [-g GROUP] [-p PORT] [-i
- -h Print the command usage.\n\n", VERSION);
- }
-
--static void igmp_join_by_saddr(int s, in_addr_t multiaddr, in_addr_t interface)
--{
-- struct ip_mreq mreq;
-- int ret;
--
-- mreq.imr_multiaddr.s_addr = multiaddr;
-- mreq.imr_interface.s_addr = interface;
--
-- ret = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP,
-- (char *)&mreq, sizeof(mreq));
-- if (ret == SOCKET_ERROR) {
-- printf("setsockopt() IP_ADD_MEMBERSHIP failed.\n");
-- exit(1);
-- }
--}
--
--static void igmp_join_by_if_name(int s, in_addr_t multicast,
-- const char *if_name)
--{
-- struct ip_mreqn mreq = {};
-- int if_index;
-- int ret;
--
-- if_index = if_nametoindex(if_name);
-- if (!if_index) {
-- perror("if_nametoindex");
-- exit(1);
-- }
--
-- mreq.imr_multiaddr.s_addr = multicast;
-- mreq.imr_ifindex = if_index;
--
-- ret = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
-- if (ret) {
-- perror("setsockopt() IP_ADD_MEMBERSHIP");
-- exit(1);
-- }
--}
--
- int main(int argc, char *argv[])
- {
-- struct sockaddr_in stLocal, stFrom;
- unsigned char achIn[BUFSIZE];
-- const char *if_name;
-- int s, i;
-- int iTmp, iRet;
-+ const char *if_name = NULL;
-+ struct ip_address mc;
-+ struct sock s, from;
- int ipnum = 0;
- int ii;
- unsigned int numreceived;
-@@ -116,6 +78,8 @@ int main(int argc, char *argv[])
- int starttime;
- int curtime;
- struct timeval tv;
-+ int ret;
-+ int i;
-
- /*
- if( argc < 2 ) {
-@@ -152,7 +116,10 @@ int main(int argc, char *argv[])
- } else if (strcmp(argv[ii], "-i") == 0) {
- ii++;
- if ((ii < argc) && !(strchr(argv[ii], '-'))) {
-- IP[ipnum] = inet_addr(argv[ii]);
-+ ret = ip_address_parse(argv[ii], &IP[ipnum]);
-+ if (ret)
-+ exit(1);
-+
- ii++;
- ipnum++;
- }
-@@ -177,73 +144,59 @@ int main(int argc, char *argv[])
- }
- }
-
-- /* get a datagram socket */
-- s = socket(AF_INET, SOCK_DGRAM, 0);
-- if (s == INVALID_SOCKET) {
-- printf("socket() failed.\n");
-+ ret = ip_address_parse(TEST_ADDR, &mc);
-+ if (ret)
- exit(1);
-- }
-
-- /* avoid EADDRINUSE error on bind() */
-- iTmp = TRUE;
-- iRet = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&iTmp, sizeof(iTmp));
-- if (iRet == SOCKET_ERROR) {
-- printf("setsockopt() SO_REUSEADDR failed.\n");
-+ if (mc.family == AF_INET6 && ipnum) {
-+ printf("Joining IPv6 groups by source address not supported, use -I\n");
- exit(1);
- }
-
-- /* name the socket */
-- stLocal.sin_family = AF_INET;
-- stLocal.sin_addr.s_addr = htonl(INADDR_ANY);
-- stLocal.sin_port = htons(TEST_PORT);
-- iRet = bind(s, (struct sockaddr *)&stLocal, sizeof(stLocal));
-- if (iRet == SOCKET_ERROR) {
-- printf("bind() failed.\n");
-+ if (mc.family == AF_INET6 && !if_name) {
-+ printf("-I is mandatory with IPv6\n");
- exit(1);
- }
-
-- /* join the multicast group. */
-- if (if_name) {
-- igmp_join_by_if_name(s, inet_addr(TEST_ADDR), if_name);
-- } else {
-- if (!ipnum) { /* single interface */
-- igmp_join_by_saddr(s, inet_addr(TEST_ADDR), INADDR_ANY);
-- } else {
-- for (i = 0; i < ipnum; i++) {
-- igmp_join_by_saddr(s, inet_addr(TEST_ADDR),
-- IP[i]);
-- }
-- }
-- }
-+ /* get a datagram socket */
-+ ret = socket_create(&s, mc.family, TEST_PORT);
-+ if (ret)
-+ exit(1);
-
-- /* set TTL to traverse up to multiple routers */
-- iTmp = TTL_VALUE;
-- iRet = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&iTmp, sizeof(iTmp));
-- if (iRet == SOCKET_ERROR) {
-- printf("setsockopt() IP_MULTICAST_TTL failed.\n");
-+ /* join the multicast group. */
-+ ret = mc_join(&s, &mc, if_name, ipnum, IP);
-+ if (ret)
- exit(1);
-- }
-
-- /* disable loopback */
-- /* iTmp = TRUE; */
-- iTmp = FALSE;
-- iRet = setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&iTmp, sizeof(iTmp));
-- if (iRet == SOCKET_ERROR) {
-- printf("setsockopt() IP_MULTICAST_LOOP failed.\n");
-+ /* set TTL to traverse up to multiple routers */
-+ ret = mc_set_hop_limit(&s, TTL_VALUE);
-+ if (ret)
- exit(1);
-- }
-
- printf("Now receiving from multicast group: %s\n", TEST_ADDR);
-
- for (i = 0;; i++) {
-- socklen_t addr_size = sizeof(struct sockaddr_in);
-+ char from_buf[INET6_ADDRSTRLEN];
- static int iCounter = 1;
-+ const char *addr_str;
-
- /* receive from the multicast address */
-
-- iRet = recvfrom(s, achIn, BUFSIZE, 0, (struct sockaddr *)&stFrom, &addr_size);
-- if (iRet < 0) {
-- printf("recvfrom() failed.\n");
-+ ret = mc_recv(&s, achIn, BUFSIZE, &from);
-+ if (ret < 0) {
-+ perror("recvfrom");
-+ exit(1);
-+ }
-+
-+ if (mc.family == AF_INET) {
-+ addr_str = inet_ntop(AF_INET, &from.udp4.sin_addr,
-+ from_buf, INET6_ADDRSTRLEN);
-+ } else {
-+ addr_str = inet_ntop(AF_INET6, &from.udp6.sin6_addr,
-+ from_buf, INET6_ADDRSTRLEN);
-+ }
-+ if (!addr_str) {
-+ perror("inet_ntop");
- exit(1);
- }
-
-@@ -256,7 +209,8 @@ int main(int argc, char *argv[])
- numreceived =
- (unsigned int)achIn[0] + ((unsigned int)(achIn[1]) << 8) + ((unsigned int)(achIn[2]) << 16) +
- ((unsigned int)(achIn[3]) >> 24);
-- fprintf(stdout, "%5d\t%s:%5d\t%d.%03d\t%5d\n", iCounter, inet_ntoa(stFrom.sin_addr), ntohs(stFrom.sin_port),
-+ fprintf(stdout, "%5d\t%s:%5d\t%d.%03d\t%5d\n", iCounter,
-+ from_buf, socket_get_port(&from),
- curtime / 1000000, (curtime % 1000000) / 1000, numreceived);
- fflush(stdout);
- rcvCountNew = numreceived;
-@@ -276,7 +230,7 @@ int main(int argc, char *argv[])
- rcvCountOld = rcvCountNew;
- } else {
- printf("Receive msg %d from %s:%d: %s\n",
-- iCounter, inet_ntoa(stFrom.sin_addr), ntohs(stFrom.sin_port), achIn);
-+ iCounter, from_buf, socket_get_port(&from), achIn);
- }
- iCounter++;
- }
+++ /dev/null
-From 9aa908fc2dd84cfed151fa260b39465978079274 Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Tue, 19 Apr 2022 19:28:59 +0300
-Subject: [PATCH 4/6] msend: support IPv6
-
-Finish the conversion by updating msend to use the common procedures
-that support IPv6.
-
-I've only tested this with a link-local source address.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- Makefile | 2 +-
- common.c | 62 +++++++++++++++++++++----
- common.h | 5 +-
- mreceive.c | 2 +-
- msend.c | 131 +++++++++++++++++++++++++++++------------------------
- 5 files changed, 132 insertions(+), 70 deletions(-)
-
---- a/Makefile
-+++ b/Makefile
-@@ -35,7 +35,7 @@ all: $(EXEC)
- @printf " LINK $@\n"
- @$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-Map,$@.map -o $@ $^ $(LDLIBS$(LDLIBS-$(@)))
-
--msend: msend.o
-+msend: msend.o common.o
- mreceive: mreceive.o common.o
- ttcp: ttcp.o
-
---- a/common.c
-+++ b/common.c
-@@ -30,7 +30,8 @@ int ip_address_parse(const char *string,
- return 0;
- }
-
--int socket_create(struct sock *s, int family, int port)
-+int socket_create(struct sock *s, int family, int port,
-+ struct ip_address *saddr, const char *if_name)
- {
- struct sockaddr *serv_addr;
- int sockopt = 1;
-@@ -40,13 +41,16 @@ int socket_create(struct sock *s, int fa
-
- if (family == AF_INET) {
- serv_addr = (struct sockaddr *)&s->udp4;
-- s->udp4.sin_addr.s_addr = htonl(INADDR_ANY);
-+ s->udp4.sin_addr = saddr ? saddr->addr :
-+ (struct in_addr) {
-+ .s_addr = htonl(INADDR_ANY),
-+ };
- s->udp4.sin_port = htons(port);
- s->udp4.sin_family = AF_INET;
- s->addr_size = sizeof(struct sockaddr_in);
- } else {
- serv_addr = (struct sockaddr *)&s->udp6;
-- s->udp6.sin6_addr = in6addr_any;
-+ s->udp6.sin6_addr = saddr ? saddr->addr6 : in6addr_any;
- s->udp6.sin6_port = htons(port);
- s->udp6.sin6_family = AF_INET6;
- s->addr_size = sizeof(struct sockaddr_in6);
-@@ -66,11 +70,22 @@ int socket_create(struct sock *s, int fa
- return ret;
- }
-
-- ret = bind(fd, serv_addr, s->addr_size);
-- if (ret) {
-- perror("bind");
-- close(fd);
-- return ret;
-+ if (if_name) {
-+ /* Bind to device, required for IPv6 link-local addresses */
-+ ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, if_name,
-+ IFNAMSIZ - 1);
-+ if (ret) {
-+ perror("setsockopt() SO_BINDTODEVICE");
-+ close(fd);
-+ return ret;
-+ }
-+ } else {
-+ ret = bind(fd, serv_addr, s->addr_size);
-+ if (ret) {
-+ perror("bind");
-+ close(fd);
-+ return ret;
-+ }
- }
-
- s->fd = fd;
-@@ -248,6 +263,12 @@ int mc_recv(struct sock *s, void *buf, s
- &from->addr_size);
- }
-
-+int mc_send(struct sock *s, struct sock *to, void *buf, size_t len)
-+{
-+ return sendto(s->fd, buf, len, 0, (struct sockaddr *)&(to->udp4),
-+ s->addr_size);
-+}
-+
- int socket_get_port(const struct sock *s)
- {
- switch (s->addr_size) {
-@@ -259,3 +280,28 @@ int socket_get_port(const struct sock *s
- return 0;
- }
- }
-+
-+int socket_set_loopback(struct sock *s, int loop)
-+{
-+ int fd = s->fd;
-+ int ret;
-+
-+ switch (s->addr_size) {
-+ case sizeof(struct sockaddr_in):
-+ ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop,
-+ sizeof(int));
-+ if (ret)
-+ perror("setsockopt IP_MULTICAST_LOOP");
-+ break;
-+ case sizeof(struct sockaddr_in6):
-+ ret = setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop,
-+ sizeof(int));
-+ if (ret)
-+ perror("setsockopt IPV6_MULTICAST_LOOP");
-+ break;
-+ default:
-+ return 0;
-+ }
-+
-+ return ret;
-+}
---- a/common.h
-+++ b/common.h
-@@ -26,11 +26,14 @@ struct sock {
- };
-
- int ip_address_parse(const char *string, struct ip_address *ip);
--int socket_create(struct sock *s, int family, int port);
-+int socket_create(struct sock *s, int family, int port,
-+ struct ip_address *saddr, const char *if_name);
- int mc_join(struct sock *s, const struct ip_address *mc, const char *if_name,
- int num_saddrs, struct ip_address *saddrs);
- int mc_set_hop_limit(struct sock *s, int limit);
- int mc_recv(struct sock *s, void *buf, size_t len, struct sock *from);
-+int mc_send(struct sock *s, struct sock *to, void *buf, size_t len);
- int socket_get_port(const struct sock *s);
-+int socket_set_loopback(struct sock *s, int loop);
-
- #endif
---- a/mreceive.c
-+++ b/mreceive.c
-@@ -159,7 +159,7 @@ int main(int argc, char *argv[])
- }
-
- /* get a datagram socket */
-- ret = socket_create(&s, mc.family, TEST_PORT);
-+ ret = socket_create(&s, mc.family, TEST_PORT, NULL, NULL);
- if (ret)
- exit(1);
-
---- a/msend.c
-+++ b/msend.c
-@@ -30,6 +30,8 @@
- #include <signal.h>
- #include <sys/time.h>
-
-+#include "common.h"
-+
- #define TRUE 1
- #define FALSE 0
- #ifndef INVALID_SOCKET
-@@ -45,18 +47,16 @@ char *TEST_ADDR = "224.1.1.1";
- int TEST_PORT = 4444;
- int TTL_VALUE = 1;
- int SLEEP_TIME = 1000;
--unsigned long IP = INADDR_ANY;
- int NUM = 0;
-
- int join_flag = 0; /* not join */
-
- typedef struct timerhandler_s {
-- int s;
-+ struct sock *s;
-+ struct sock *to;
- char *achOut;
- int len;
- int n;
-- struct sockaddr *stTo;
-- int addr_size;
- } timerhandler_t;
- timerhandler_t handler_par;
- void timerhandler();
-@@ -87,16 +87,15 @@ Usage: msend [-g GROUP] [-p PORT] [-joi
-
- int main(int argc, char *argv[])
- {
-- struct sockaddr_in stLocal, stTo;
-+ struct ip_address *saddr = NULL, mc;
-+ struct sock s = {}, to = {};
-+ const char *if_name = NULL;
- char achOut[BUFSIZE] = "";
-- int s, i;
-- struct ip_mreq stMreq;
-- int iTmp, iRet;
- int ii = 1;
-- int addr_size = sizeof(struct sockaddr_in);
- struct itimerval times;
- sigset_t sigset;
- struct sigaction act;
-+ int ret, i;
-
- if ((argc == 2) && (strcmp(argv[ii], "-v") == 0)) {
- printf("msend version 2.2\n");
-@@ -126,7 +125,32 @@ int main(int argc, char *argv[])
- } else if (strcmp(argv[ii], "-i") == 0) {
- ii++;
- if ((ii < argc) && !(strchr(argv[ii], '-'))) {
-- IP = inet_addr(argv[ii]);
-+ if (saddr) {
-+ printf("Single source address allowed\n");
-+ exit(1);
-+ }
-+
-+ saddr = calloc(1, sizeof(*saddr));
-+ if (!saddr) {
-+ printf("Low memory\n");
-+ exit(1);
-+ }
-+
-+ ret = ip_address_parse(argv[ii], saddr);
-+ if (ret)
-+ exit(1);
-+
-+ ii++;
-+ }
-+ } else if (strcmp(argv[ii], "-I") == 0) {
-+ ii++;
-+ if (ii < argc) {
-+ if (if_name) {
-+ printf("Single interface expected\n");
-+ exit(1);
-+ }
-+
-+ if_name = argv[ii];
- ii++;
- }
- } else if (strcmp(argv[ii], "-t") == 0) {
-@@ -158,62 +182,50 @@ int main(int argc, char *argv[])
- }
- }
-
-- /* get a datagram socket */
-- s = socket(AF_INET, SOCK_DGRAM, 0);
-- if (s == INVALID_SOCKET) {
-- printf("socket() failed.\n");
-+ ret = ip_address_parse(TEST_ADDR, &mc);
-+ if (ret)
- exit(1);
-- }
-
-- /* avoid EADDRINUSE error on bind() */
-- iTmp = TRUE;
-- iRet = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&iTmp, sizeof(iTmp));
-- if (iRet == SOCKET_ERROR) {
-- printf("setsockopt() SO_REUSEADDR failed.\n");
-+ if (join_flag && mc.family == AF_INET6 && !if_name) {
-+ printf("-I is mandatory when joining IPv6 group\n");
- exit(1);
- }
-
-- /* name the socket */
-- stLocal.sin_family = AF_INET;
-- stLocal.sin_addr.s_addr = IP;
-- stLocal.sin_port = htons(TEST_PORT);
-- iRet = bind(s, (struct sockaddr *)&stLocal, sizeof(stLocal));
-- if (iRet == SOCKET_ERROR) {
-- printf("bind() failed.\n");
-+ /* get a datagram socket */
-+ ret = socket_create(&s, mc.family, TEST_PORT, saddr, if_name);
-+ if (ret)
- exit(1);
-- }
-
- /* join the multicast group. */
-- stMreq.imr_multiaddr.s_addr = inet_addr(TEST_ADDR);
-- stMreq.imr_interface.s_addr = IP;
- if (join_flag == 1) {
-- iRet = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&stMreq, sizeof(stMreq));
-- if (iRet == SOCKET_ERROR) {
-- printf("setsockopt() IP_ADD_MEMBERSHIP failed.\n");
-+ ret = mc_join(&s, &mc, if_name, 0, NULL);
-+ if (ret)
- exit(1);
-- }
- }
-
- /* set TTL to traverse up to multiple routers */
-- iTmp = TTL_VALUE;
-- iRet = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&iTmp, sizeof(iTmp));
-- if (iRet == SOCKET_ERROR) {
-- printf("setsockopt() IP_MULTICAST_TTL failed.\n");
-+ ret = mc_set_hop_limit(&s, TTL_VALUE);
-+ if (ret)
- exit(1);
-- }
-
- /* enable loopback */
-- iTmp = TRUE;
-- iRet = setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&iTmp, sizeof(iTmp));
-- if (iRet == SOCKET_ERROR) {
-- printf("setsockopt() IP_MULTICAST_LOOP failed.\n");
-+ ret = socket_set_loopback(&s, 1);
-+ if (ret)
- exit(1);
-- }
-
- /* assign our destination address */
-- stTo.sin_family = AF_INET;
-- stTo.sin_addr.s_addr = inet_addr(TEST_ADDR);
-- stTo.sin_port = htons(TEST_PORT);
-+ if (mc.family == AF_INET) {
-+ to.udp4.sin_addr = mc.addr;
-+ to.udp4.sin_port = htons(TEST_PORT);
-+ to.udp4.sin_family = AF_INET;
-+ to.addr_size = sizeof(struct sockaddr_in);
-+ } else {
-+ to.udp6.sin6_addr = mc.addr6;
-+ to.udp6.sin6_port = htons(TEST_PORT);
-+ to.udp6.sin6_family = AF_INET6;
-+ to.addr_size = sizeof(struct sockaddr_in6);
-+ }
-+
- printf("Now sending to multicast group: %s\n", TEST_ADDR);
-
- SLEEP_TIME *= 1000; /* convert to microsecond */
-@@ -237,12 +249,11 @@ int main(int argc, char *argv[])
- times.it_interval.tv_usec = (long)(SLEEP_TIME % 1000000);
- setitimer(ITIMER_REAL, ×, NULL);
-
-- handler_par.s = s;
-+ handler_par.s = &s;
-+ handler_par.to = &to;
- handler_par.achOut = achOut;
- handler_par.len = strlen(achOut) + 1;
- handler_par.n = 0;
-- handler_par.stTo = (struct sockaddr *)&stTo;
-- handler_par.addr_size = addr_size;
-
- /* now wait for the alarms */
- sigemptyset(&sigset);
-@@ -252,8 +263,6 @@ int main(int argc, char *argv[])
- return 0;
- } else {
- for (i = 0; i < 10; i++) {
-- int addr_size = sizeof(struct sockaddr_in);
--
- if (NUM) {
- achOut[3] = (unsigned char)(i >> 24);
- achOut[2] = (unsigned char)(i >> 16);
-@@ -264,9 +273,10 @@ int main(int argc, char *argv[])
- printf("Send out msg %d to %s:%d: %s\n", i, TEST_ADDR, TEST_PORT, achOut);
- }
-
-- iRet = sendto(s, achOut, (NUM ? 4 : strlen(achOut) + 1), 0, (struct sockaddr *)&stTo, addr_size);
-- if (iRet < 0) {
-- printf("sendto() failed.\n");
-+ ret = mc_send(&s, &to, achOut,
-+ NUM ? 4 : strlen(achOut) + 1);
-+ if (ret < 0) {
-+ perror("sendto");
- exit(1);
- }
- } /* end for(;;) */
-@@ -277,8 +287,8 @@ int main(int argc, char *argv[])
-
- void timerhandler(void)
- {
-- int iRet;
- static int iCounter = 1;
-+ int ret;
-
- if (NUM) {
- handler_par.achOut = (char *)(&iCounter);
-@@ -287,11 +297,14 @@ void timerhandler(void)
- } else {
- printf("Sending msg %d, TTL %d, to %s:%d: %s\n", iCounter, TTL_VALUE, TEST_ADDR, TEST_PORT, handler_par.achOut);
- }
-- iRet = sendto(handler_par.s, handler_par.achOut, handler_par.len, handler_par.n, handler_par.stTo, handler_par.addr_size);
-- if (iRet < 0) {
-- printf("sendto() failed.\n");
-+
-+ ret = mc_send(handler_par.s, handler_par.to, handler_par.achOut,
-+ handler_par.len);
-+ if (ret < 0) {
-+ perror("sendto");
- exit(1);
- }
-+
- iCounter++;
- return;
- }
+++ /dev/null
-From bf95bdeccab98cec77dc1b10bce0b215754e4e46 Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Thu, 21 Apr 2022 16:45:08 +0300
-Subject: [PATCH 5/6] mreceive: msend: add new -I option to the help text
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- mreceive.c | 2 ++
- msend.c | 2 ++
- 2 files changed, 4 insertions(+)
-
---- a/mreceive.c
-+++ b/mreceive.c
-@@ -58,6 +58,8 @@ Usage: mreceive [-g GROUP] [-p PORT] [-i
- -p PORT UDP port number used in the multicast packets. Default: 4444\n\
- -i ADDRESS IP addresses of one or more interfaces to listen for the given\n\
- multicast group. Default: the system default interface.\n\
-+ -I interface The interface on which to receive. Can be specified as an\n\
-+ alternative to -i.\n\
- -n Interpret the contents of the message as a number instead of\n\
- a string of characters. Use this with `msend -n`\n\
- -v Print version information.\n\
---- a/msend.c
-+++ b/msend.c
-@@ -72,6 +72,8 @@ Usage: msend [-g GROUP] [-p PORT] [-joi
- -p PORT UDP port number used in the multicast packets. Default: 4444\n\
- -i ADDRESS IP address of the interface to use to send the packets.\n\
- The default is to use the system default interface.\n\
-+ -I interface The interface on which to send. Can be specified as an\n\
-+ alternative to -i.\n\
- -join Multicast sender will join the multicast group.\n\
- By default a sender never joins the group.\n\
- -P PERIOD Interval in milliseconds between packets. Default 1000 msec\n\
+++ /dev/null
-From 1013b0a83aef868e6cd33b2f467b9f886b41e7bc Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Fri, 22 Apr 2022 12:59:56 +0300
-Subject: [PATCH 6/6] msend: send a limited number of test packets
-
-For easier integration into a selftest framework, limit the amount of
-packets that the program sends via a command-line argument.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- msend.c | 17 ++++++++++++++---
- 1 file changed, 14 insertions(+), 3 deletions(-)
-
---- a/msend.c
-+++ b/msend.c
-@@ -56,7 +56,7 @@ typedef struct timerhandler_s {
- struct sock *to;
- char *achOut;
- int len;
-- int n;
-+ int num_pkts;
- } timerhandler_t;
- timerhandler_t handler_par;
- void timerhandler();
-@@ -82,6 +82,7 @@ Usage: msend [-g GROUP] [-p PORT] [-joi
- the first router will drop the packets! Default: 1\n\
- -text \"text\" Specify a string to use as payload in the packets, also\n\
- displayed by the mreceive command. Default: empty\n\
-+ -c Number of packets to send. Default: send indefinitely\n\
- -n Encode -text argument as a number instead of a string.\n\
- -v Print version information.\n\
- -h Print the command usage.\n\n", VERSION);
-@@ -97,6 +98,7 @@ int main(int argc, char *argv[])
- struct itimerval times;
- sigset_t sigset;
- struct sigaction act;
-+ int num_pkts = 0;
- int ret, i;
-
- if ((argc == 2) && (strcmp(argv[ii], "-v") == 0)) {
-@@ -171,6 +173,12 @@ int main(int argc, char *argv[])
- ii++;
- NUM = 1;
- ii++;
-+ } else if (strcmp(argv[ii], "-c") == 0) {
-+ ii++;
-+ if ((ii < argc) && !(strchr(argv[ii], '-'))) {
-+ num_pkts = atoi(argv[ii]);
-+ ii++;
-+ }
- } else if (strcmp(argv[ii], "-text") == 0) {
- ii++;
- if ((ii < argc) && !(strchr(argv[ii], '-'))) {
-@@ -255,7 +263,7 @@ int main(int argc, char *argv[])
- handler_par.to = &to;
- handler_par.achOut = achOut;
- handler_par.len = strlen(achOut) + 1;
-- handler_par.n = 0;
-+ handler_par.num_pkts = num_pkts;
-
- /* now wait for the alarms */
- sigemptyset(&sigset);
-@@ -264,7 +272,7 @@ int main(int argc, char *argv[])
- }
- return 0;
- } else {
-- for (i = 0; i < 10; i++) {
-+ for (i = 0; num_pkts && i < num_pkts; i++) {
- if (NUM) {
- achOut[3] = (unsigned char)(i >> 24);
- achOut[2] = (unsigned char)(i >> 16);
-@@ -307,6 +315,9 @@ void timerhandler(void)
- exit(1);
- }
-
-+ if (iCounter == handler_par.num_pkts)
-+ exit(1);
-+
- iCounter++;
- return;
- }
+++ /dev/null
-From e0c9115e1ceb6621d6c04ae8bfd423a0452fea9c Mon Sep 17 00:00:00 2001
-From: Christian Marangi <ansuelsmth@gmail.com>
-Date: Wed, 5 Jul 2023 11:03:40 +0200
-Subject: [PATCH] mreceive: msend: fix wrong version in -v output
-
--v output was never changed to follow VERSION declared in Makefile and
-was still hardcoded. Fix this to improve version output and align to -h
-output.
-
-Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
----
- mreceive.c | 2 +-
- msend.c | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
---- a/mreceive.c
-+++ b/mreceive.c
-@@ -93,7 +93,7 @@ int main(int argc, char *argv[])
- ii = 1;
-
- if ((argc == 2) && (strcmp(argv[ii], "-v") == 0)) {
-- printf("mreceive version 2.2\n");
-+ printf("mreceive version %s\n", VERSION);
- return 0;
- }
- if ((argc == 2) && (strcmp(argv[ii], "-h") == 0)) {
---- a/msend.c
-+++ b/msend.c
-@@ -102,7 +102,7 @@ int main(int argc, char *argv[])
- int ret, i;
-
- if ((argc == 2) && (strcmp(argv[ii], "-v") == 0)) {
-- printf("msend version 2.2\n");
-+ printf("msend version %s\n", VERSION);
- return 0;
- }
- if ((argc == 2) && (strcmp(argv[ii], "-h") == 0)) {