diff --git a/net/net-mtools/Makefile b/net/net-mtools/Makefile index 1c0c3d26b..8d0295fe4 100644 --- a/net/net-mtools/Makefile +++ b/net/net-mtools/Makefile @@ -1,13 +1,13 @@ 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 diff --git a/net/net-mtools/patches/001-mreceive-refactor-multicast-joining-to-separate-func.patch b/net/net-mtools/patches/001-mreceive-refactor-multicast-joining-to-separate-func.patch deleted file mode 100644 index db96daedf..000000000 --- a/net/net-mtools/patches/001-mreceive-refactor-multicast-joining-to-separate-func.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0cfc04eac370ee33118e17a298d4739c94cacc73 Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -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 ---- - 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]); - } - } - diff --git a/net/net-mtools/patches/002-mreceive-join-IGMP-group-by-interface.patch b/net/net-mtools/patches/002-mreceive-join-IGMP-group-by-interface.patch deleted file mode 100644 index 5959062f9..000000000 --- a/net/net-mtools/patches/002-mreceive-join-IGMP-group-by-interface.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 65af96e0907ba9367aab9c1534b11c7f674c1e6a Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -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 ---- - mreceive.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- - 1 file changed, 46 insertions(+), 5 deletions(-) - ---- a/mreceive.c -+++ b/mreceive.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -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]); -+ } - } - } - diff --git a/net/net-mtools/patches/003-mreceive-support-IPv6.patch b/net/net-mtools/patches/003-mreceive-support-IPv6.patch deleted file mode 100644 index cfd1ab2cf..000000000 --- a/net/net-mtools/patches/003-mreceive-support-IPv6.patch +++ /dev/null @@ -1,578 +0,0 @@ -From cc7f68045e5f3cfc6c932996af784ab319951426 Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -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 ---- - 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 -+#include -+#include -+#include -+#include -+ -+#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 -+#include -+#include -+ -+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 - #include - -+#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++; - } diff --git a/net/net-mtools/patches/004-msend-support-IPv6.patch b/net/net-mtools/patches/004-msend-support-IPv6.patch deleted file mode 100644 index 84d517538..000000000 --- a/net/net-mtools/patches/004-msend-support-IPv6.patch +++ /dev/null @@ -1,401 +0,0 @@ -From 9aa908fc2dd84cfed151fa260b39465978079274 Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -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 ---- - 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 - #include - -+#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; - } diff --git a/net/net-mtools/patches/005-mreceive-msend-add-new-I-option-to-the-help-text.patch b/net/net-mtools/patches/005-mreceive-msend-add-new-I-option-to-the-help-text.patch deleted file mode 100644 index 73af1d14e..000000000 --- a/net/net-mtools/patches/005-mreceive-msend-add-new-I-option-to-the-help-text.patch +++ /dev/null @@ -1,33 +0,0 @@ -From bf95bdeccab98cec77dc1b10bce0b215754e4e46 Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -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 ---- - 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\ diff --git a/net/net-mtools/patches/006-msend-send-a-limited-number-of-test-packets.patch b/net/net-mtools/patches/006-msend-send-a-limited-number-of-test-packets.patch deleted file mode 100644 index 8e8db738e..000000000 --- a/net/net-mtools/patches/006-msend-send-a-limited-number-of-test-packets.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 1013b0a83aef868e6cd33b2f467b9f886b41e7bc Mon Sep 17 00:00:00 2001 -From: Vladimir Oltean -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 ---- - 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; - } diff --git a/net/net-mtools/patches/100-mreceive-msend-fix-wrong-version-in-v-output.patch b/net/net-mtools/patches/100-mreceive-msend-fix-wrong-version-in-v-output.patch deleted file mode 100644 index 2ba867745..000000000 --- a/net/net-mtools/patches/100-mreceive-msend-fix-wrong-version-in-v-output.patch +++ /dev/null @@ -1,37 +0,0 @@ -From e0c9115e1ceb6621d6c04ae8bfd423a0452fea9c Mon Sep 17 00:00:00 2001 -From: Christian Marangi -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 ---- - 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)) {