^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* nettest - used for functional tests of networking APIs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2013-2019 David Ahern <dsahern@gmail.com>. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #define _GNU_SOURCE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <features.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <sys/ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <sys/socket.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/tcp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <arpa/inet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <net/if.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <netinet/in.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <netdb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <libgen.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <limits.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <stdarg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #ifndef IPV6_UNICAST_IF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define IPV6_UNICAST_IF 76
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #ifndef IPV6_MULTICAST_IF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define IPV6_MULTICAST_IF 17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define DEFAULT_PORT 12345
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #ifndef MAX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define MAX(a, b) ((a) > (b) ? (a) : (b))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #ifndef MIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define MIN(a, b) ((a) < (b) ? (a) : (b))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct sock_args {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* local address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct in_addr in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct in6_addr in6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) } local_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* remote address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct in_addr in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct in6_addr in6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) } remote_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int scope_id; /* remote scope; v6 send only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct in_addr grp; /* multicast group */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) unsigned int has_local_ip:1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) has_remote_ip:1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) has_grp:1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) has_expected_laddr:1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) has_expected_raddr:1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) bind_test_only:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) unsigned short port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) int type; /* DGRAM, STREAM, RAW */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) int protocol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int version; /* AF_INET/AF_INET6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) int use_setsockopt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int use_cmsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) const char *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) const char *password;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* prefix for MD5 password */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct sockaddr_in v4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct sockaddr_in6 v6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) } md5_prefix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) unsigned int prefix_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* expected addresses and device index for connection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) int expected_ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* local address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct in_addr in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct in6_addr in6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) } expected_laddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /* remote address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct in_addr in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct in6_addr in6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) } expected_raddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static int server_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static unsigned int prog_timeout = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static unsigned int interactive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static int iter = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static char *msg = "Hello world!";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static int msglen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static int quiet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static int try_broadcast = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static char *timestamp(char *timebuf, int buflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) time_t now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) now = time(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (strftime(timebuf, buflen, "%T", localtime(&now)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) memset(timebuf, 0, buflen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) strncpy(timebuf, "00:00:00", buflen-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return timebuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static void log_msg(const char *format, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) char timebuf[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (quiet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) fprintf(stdout, "%s %s:",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) timestamp(timebuf, sizeof(timebuf)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) server_mode ? "server" : "client");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) va_start(args, format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) vfprintf(stdout, format, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static void log_error(const char *format, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) char timebuf[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (quiet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) fprintf(stderr, "%s %s:",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) timestamp(timebuf, sizeof(timebuf)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) server_mode ? "server" : "client");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) va_start(args, format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) vfprintf(stderr, format, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) fflush(stderr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static void log_err_errno(const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) char timebuf[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (quiet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) fprintf(stderr, "%s %s: ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) timestamp(timebuf, sizeof(timebuf)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) server_mode ? "server" : "client");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) vfprintf(stderr, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) fprintf(stderr, ": %d: %s\n", errno, strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) fflush(stderr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static void log_address(const char *desc, struct sockaddr *sa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) char addrstr[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (quiet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (sa->sa_family == AF_INET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct sockaddr_in *s = (struct sockaddr_in *) sa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) log_msg("%s %s:%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) inet_ntop(AF_INET, &s->sin_addr, addrstr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) sizeof(addrstr)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) ntohs(s->sin_port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) } else if (sa->sa_family == AF_INET6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) log_msg("%s [%s]:%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) inet_ntop(AF_INET6, &s6->sin6_addr, addrstr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) sizeof(addrstr)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) ntohs(s6->sin6_port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static int tcp_md5sig(int sd, void *addr, socklen_t alen, struct sock_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) int keylen = strlen(args->password);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct tcp_md5sig md5sig = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) int opt = TCP_MD5SIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) md5sig.tcpm_keylen = keylen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) memcpy(md5sig.tcpm_key, args->password, keylen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (args->prefix_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) opt = TCP_MD5SIG_EXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) md5sig.tcpm_flags |= TCP_MD5SIG_FLAG_PREFIX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) md5sig.tcpm_prefixlen = args->prefix_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) addr = &args->md5_prefix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) memcpy(&md5sig.tcpm_addr, addr, alen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (args->ifindex) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) opt = TCP_MD5SIG_EXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) md5sig.tcpm_flags |= TCP_MD5SIG_FLAG_IFINDEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) md5sig.tcpm_ifindex = args->ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) rc = setsockopt(sd, IPPROTO_TCP, opt, &md5sig, sizeof(md5sig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /* ENOENT is harmless. Returned when a password is cleared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (errno == ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) log_err_errno("setsockopt(TCP_MD5SIG)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static int tcp_md5_remote(int sd, struct sock_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct sockaddr_in sin = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) .sin_family = AF_INET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) struct sockaddr_in6 sin6 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) .sin6_family = AF_INET6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) void *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) int alen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) switch (args->version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) case AF_INET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) sin.sin_port = htons(args->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) sin.sin_addr = args->remote_addr.in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) addr = &sin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) alen = sizeof(sin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) case AF_INET6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) sin6.sin6_port = htons(args->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) sin6.sin6_addr = args->remote_addr.in6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) addr = &sin6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) alen = sizeof(sin6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) log_error("unknown address family\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (tcp_md5sig(sd, addr, alen, args))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) static int get_ifidx(const char *ifname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct ifreq ifdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) int sd, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (!ifname || *ifname == '\0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) memset(&ifdata, 0, sizeof(ifdata));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) strcpy(ifdata.ifr_name, ifname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (sd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) log_err_errno("socket failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) rc = ioctl(sd, SIOCGIFINDEX, (char *)&ifdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) close(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) log_err_errno("ioctl(SIOCGIFINDEX) failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return ifdata.ifr_ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static int bind_to_device(int sd, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) rc = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name)+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) log_err_errno("setsockopt(SO_BINDTODEVICE)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) static int get_bind_to_device(int sd, char *name, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) socklen_t optlen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) name[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) rc = getsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, name, &optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) log_err_errno("setsockopt(SO_BINDTODEVICE)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static int check_device(int sd, struct sock_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) int ifindex = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) char name[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (get_bind_to_device(sd, name, sizeof(name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) *name = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) ifindex = get_ifidx(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) log_msg(" bound to device %s/%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) *name ? name : "<none>", ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (!args->expected_ifindex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (args->expected_ifindex != ifindex) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) log_error("Device index mismatch: expected %d have %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) args->expected_ifindex, ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) log_msg("Device index matches: expected %d have %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) args->expected_ifindex, ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static int set_pktinfo_v4(int sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) int one = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) rc = setsockopt(sd, SOL_IP, IP_PKTINFO, &one, sizeof(one));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (rc < 0 && rc != -ENOTSUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) log_err_errno("setsockopt(IP_PKTINFO)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) static int set_recvpktinfo_v6(int sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) int one = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) rc = setsockopt(sd, SOL_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (rc < 0 && rc != -ENOTSUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) log_err_errno("setsockopt(IPV6_RECVPKTINFO)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) static int set_recverr_v4(int sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) int one = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) rc = setsockopt(sd, SOL_IP, IP_RECVERR, &one, sizeof(one));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (rc < 0 && rc != -ENOTSUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) log_err_errno("setsockopt(IP_RECVERR)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) static int set_recverr_v6(int sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) int one = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) rc = setsockopt(sd, SOL_IPV6, IPV6_RECVERR, &one, sizeof(one));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (rc < 0 && rc != -ENOTSUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) log_err_errno("setsockopt(IPV6_RECVERR)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static int set_unicast_if(int sd, int ifindex, int version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) int opt = IP_UNICAST_IF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) int level = SOL_IP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) ifindex = htonl(ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (version == AF_INET6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) opt = IPV6_UNICAST_IF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) level = SOL_IPV6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) rc = setsockopt(sd, level, opt, &ifindex, sizeof(ifindex));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) log_err_errno("setsockopt(IP_UNICAST_IF)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) static int set_multicast_if(int sd, int ifindex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) struct ip_mreqn mreq = { .imr_ifindex = ifindex };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) rc = setsockopt(sd, SOL_IP, IP_MULTICAST_IF, &mreq, sizeof(mreq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) log_err_errno("setsockopt(IP_MULTICAST_IF)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static int set_membership(int sd, uint32_t grp, uint32_t addr, int ifindex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) uint32_t if_addr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) struct ip_mreqn mreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (addr == htonl(INADDR_ANY) && !ifindex) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) log_error("Either local address or device needs to be given for multicast membership\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) mreq.imr_multiaddr.s_addr = grp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) mreq.imr_address.s_addr = if_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) mreq.imr_ifindex = ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) rc = setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) log_err_errno("setsockopt(IP_ADD_MEMBERSHIP)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static int set_broadcast(int sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) unsigned int one = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (setsockopt(sd, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one)) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) log_err_errno("setsockopt(SO_BROADCAST)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) rc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) static int set_reuseport(int sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) unsigned int one = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) log_err_errno("setsockopt(SO_REUSEPORT)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) rc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) static int set_reuseaddr(int sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) unsigned int one = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) log_err_errno("setsockopt(SO_REUSEADDR)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) rc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) static int str_to_uint(const char *str, int min, int max, unsigned int *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) int number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) char *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) errno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) number = (unsigned int) strtoul(str, &end, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) /* entire string should be consumed by conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * and value should be between min and max
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (((*end == '\0') || (*end == '\n')) && (end != str) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) (errno != ERANGE) && (min <= number) && (number <= max)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) *value = number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static int expected_addr_match(struct sockaddr *sa, void *expected,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) const char *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) char addrstr[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (sa->sa_family == AF_INET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) struct sockaddr_in *s = (struct sockaddr_in *) sa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) struct in_addr *exp_in = (struct in_addr *) expected;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (s->sin_addr.s_addr != exp_in->s_addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) log_error("%s address does not match expected %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) inet_ntop(AF_INET, exp_in,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) addrstr, sizeof(addrstr)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) } else if (sa->sa_family == AF_INET6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct in6_addr *exp_in = (struct in6_addr *) expected;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (memcmp(&s6->sin6_addr, exp_in, sizeof(*exp_in))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) log_error("%s address does not match expected %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) inet_ntop(AF_INET6, exp_in,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) addrstr, sizeof(addrstr)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) log_error("%s address does not match expected - unknown family",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) log_msg("%s address matches expected\n", desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) static int show_sockstat(int sd, struct sock_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) struct sockaddr_in6 local_addr, remote_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) socklen_t alen = sizeof(local_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) struct sockaddr *sa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) const char *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) desc = server_mode ? "server local:" : "client local:";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) sa = (struct sockaddr *) &local_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (getsockname(sd, sa, &alen) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) log_address(desc, sa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (args->has_expected_laddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) rc = expected_addr_match(sa, &args->expected_laddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) "local");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) log_err_errno("getsockname failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) sa = (struct sockaddr *) &remote_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) desc = server_mode ? "server peer:" : "client peer:";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (getpeername(sd, sa, &alen) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) log_address(desc, sa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (args->has_expected_raddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) rc |= expected_addr_match(sa, &args->expected_raddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) "remote");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) log_err_errno("getpeername failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) static int get_index_from_cmsg(struct msghdr *m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) struct cmsghdr *cm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) int ifindex = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) char buf[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) m->msg_controllen != 0 && cm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) cm = (struct cmsghdr *)CMSG_NXTHDR(m, cm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (cm->cmsg_level == SOL_IP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) cm->cmsg_type == IP_PKTINFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) struct in_pktinfo *pi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) pi = (struct in_pktinfo *)(CMSG_DATA(cm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) inet_ntop(AF_INET, &pi->ipi_addr, buf, sizeof(buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) ifindex = pi->ipi_ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) } else if (cm->cmsg_level == SOL_IPV6 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) cm->cmsg_type == IPV6_PKTINFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) struct in6_pktinfo *pi6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) pi6 = (struct in6_pktinfo *)(CMSG_DATA(cm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) inet_ntop(AF_INET6, &pi6->ipi6_addr, buf, sizeof(buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) ifindex = pi6->ipi6_ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (ifindex) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) log_msg(" pktinfo: ifindex %d dest addr %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) ifindex, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) return ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) static int send_msg_no_cmsg(int sd, void *addr, socklen_t alen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) again:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) err = sendto(sd, msg, msglen, 0, addr, alen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (errno == EACCES && try_broadcast) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) try_broadcast = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (!set_broadcast(sd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) goto again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) errno = EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) log_err_errno("sendto failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) static int send_msg_cmsg(int sd, void *addr, socklen_t alen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) int ifindex, int version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) unsigned char cmsgbuf[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) struct iovec iov[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) struct cmsghdr *cm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) struct msghdr m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) iov[0].iov_base = msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) iov[0].iov_len = msglen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) m.msg_iov = iov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) m.msg_iovlen = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) m.msg_name = (caddr_t)addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) m.msg_namelen = alen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) memset(cmsgbuf, 0, sizeof(cmsgbuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) cm = (struct cmsghdr *)cmsgbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) m.msg_control = (caddr_t)cm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (version == AF_INET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) struct in_pktinfo *pi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) cm->cmsg_level = SOL_IP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) cm->cmsg_type = IP_PKTINFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) cm->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) pi = (struct in_pktinfo *)(CMSG_DATA(cm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) pi->ipi_ifindex = ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) m.msg_controllen = cm->cmsg_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) } else if (version == AF_INET6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) struct in6_pktinfo *pi6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) cm->cmsg_level = SOL_IPV6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) cm->cmsg_type = IPV6_PKTINFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) pi6 = (struct in6_pktinfo *)(CMSG_DATA(cm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) pi6->ipi6_ifindex = ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) m.msg_controllen = cm->cmsg_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) again:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) err = sendmsg(sd, &m, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (errno == EACCES && try_broadcast) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) try_broadcast = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (!set_broadcast(sd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) goto again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) errno = EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) log_err_errno("sendmsg failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) static int send_msg(int sd, void *addr, socklen_t alen, struct sock_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (args->type == SOCK_STREAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (write(sd, msg, msglen) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) log_err_errno("write failed sending msg to peer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) } else if (args->ifindex && args->use_cmsg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (send_msg_cmsg(sd, addr, alen, args->ifindex, args->version))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (send_msg_no_cmsg(sd, addr, alen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) log_msg("Sent message:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) log_msg(" %.24s%s\n", msg, msglen > 24 ? " ..." : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) static int socket_read_dgram(int sd, struct sock_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) unsigned char addr[sizeof(struct sockaddr_in6)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) struct sockaddr *sa = (struct sockaddr *) addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) socklen_t alen = sizeof(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) struct iovec iov[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) struct msghdr m = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) .msg_name = (caddr_t)addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) .msg_namelen = alen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) .msg_iov = iov,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) .msg_iovlen = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) unsigned char cmsgbuf[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) struct cmsghdr *cm = (struct cmsghdr *)cmsgbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) char buf[16*1024];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) int ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) iov[0].iov_base = (caddr_t)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) iov[0].iov_len = sizeof(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) memset(cmsgbuf, 0, sizeof(cmsgbuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) m.msg_control = (caddr_t)cm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) m.msg_controllen = sizeof(cmsgbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) len = recvmsg(sd, &m, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (len == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) log_msg("peer closed connection.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) } else if (len < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) log_msg("failed to read message: %d: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) errno, strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) buf[len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) log_address("Message from:", sa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) log_msg(" %.24s%s\n", buf, len > 24 ? " ..." : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) ifindex = get_index_from_cmsg(&m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) if (args->expected_ifindex) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) if (args->expected_ifindex != ifindex) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) log_error("Device index mismatch: expected %d have %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) args->expected_ifindex, ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) log_msg("Device index matches: expected %d have %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) args->expected_ifindex, ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) if (!interactive && server_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (sa->sa_family == AF_INET6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) struct in6_addr *in6 = &s6->sin6_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) if (IN6_IS_ADDR_V4MAPPED(in6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) const uint32_t *pa = (uint32_t *) &in6->s6_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) struct in_addr in4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) struct sockaddr_in *sin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) sin = (struct sockaddr_in *) addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) pa += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) in4.s_addr = *pa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) sin->sin_addr = in4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) sin->sin_family = AF_INET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if (send_msg_cmsg(sd, addr, alen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) ifindex, AF_INET) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) again:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) iov[0].iov_len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (args->version == AF_INET6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (args->dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) /* avoid PKTINFO conflicts with bindtodev */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (sendto(sd, buf, len, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) (void *) addr, alen) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) /* kernel is allowing scope_id to be set to VRF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) * index for LLA. for sends to global address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) * reset scope id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) s6->sin6_scope_id = ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (sendmsg(sd, &m, 0) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) err = sendmsg(sd, &m, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (errno == EACCES && try_broadcast) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) try_broadcast = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (!set_broadcast(sd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) goto again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) errno = EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) log_msg("Sent message:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) log_msg(" %.24s%s\n", buf, len > 24 ? " ..." : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) log_err_errno("failed to send msg to peer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) static int socket_read_stream(int sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) char buf[1024];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) len = read(sd, buf, sizeof(buf)-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (len == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) log_msg("client closed connection.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) } else if (len < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) log_msg("failed to read message\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) buf[len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) log_msg("Incoming message:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) log_msg(" %.24s%s\n", buf, len > 24 ? " ..." : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (!interactive && server_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (write(sd, buf, len) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) log_err_errno("failed to send buf");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) log_msg("Sent message:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) log_msg(" %.24s%s\n", buf, len > 24 ? " ..." : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) static int socket_read(int sd, struct sock_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (args->type == SOCK_STREAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return socket_read_stream(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) return socket_read_dgram(sd, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) static int stdin_to_socket(int sd, int type, void *addr, socklen_t alen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) char buf[1024];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (fgets(buf, sizeof(buf), stdin) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) len = strlen(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (type == SOCK_STREAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (write(sd, buf, len) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) log_err_errno("failed to send buf");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) again:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) err = sendto(sd, buf, len, 0, addr, alen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if (errno == EACCES && try_broadcast) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) try_broadcast = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) if (!set_broadcast(sd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) goto again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) errno = EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) log_err_errno("failed to send msg to peer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) log_msg("Sent message:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) log_msg(" %.24s%s\n", buf, len > 24 ? " ..." : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) static void set_recv_attr(int sd, int version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) if (version == AF_INET6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) set_recvpktinfo_v6(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) set_recverr_v6(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) set_pktinfo_v4(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) set_recverr_v4(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) static int msg_loop(int client, int sd, void *addr, socklen_t alen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) struct sock_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct timeval timeout = { .tv_sec = prog_timeout }, *ptval = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) fd_set rfds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) int nfds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (args->type != SOCK_STREAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) set_recv_attr(sd, args->version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (msg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) msglen = strlen(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) /* client sends first message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) if (client) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) if (send_msg(sd, addr, alen, args))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) if (!interactive) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) ptval = &timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) if (!prog_timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) timeout.tv_sec = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) nfds = interactive ? MAX(fileno(stdin), sd) + 1 : sd + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) FD_ZERO(&rfds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) FD_SET(sd, &rfds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) if (interactive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) FD_SET(fileno(stdin), &rfds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) rc = select(nfds, &rfds, NULL, NULL, ptval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) if (errno == EINTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) log_err_errno("select failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) } else if (rc == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) log_error("Timed out waiting for response\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) rc = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) if (FD_ISSET(sd, &rfds)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) rc = socket_read(sd, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (rc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (FD_ISSET(fileno(stdin), &rfds)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) if (stdin_to_socket(sd, args->type, addr, alen) <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) if (interactive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if (iter != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) --iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (iter == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) log_msg("Going into quiet mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) quiet = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (client) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) if (send_msg(sd, addr, alen, args)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) static int msock_init(struct sock_args *args, int server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) uint32_t if_addr = htonl(INADDR_ANY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) struct sockaddr_in laddr = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) .sin_family = AF_INET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) .sin_port = htons(args->port),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) int one = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) int sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) if (!server && args->has_local_ip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if_addr = args->local_addr.in.s_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) sd = socket(PF_INET, SOCK_DGRAM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) if (sd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) log_err_errno("socket");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) (char *)&one, sizeof(one)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) log_err_errno("Setting SO_REUSEADDR error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) if (setsockopt(sd, SOL_SOCKET, SO_BROADCAST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) (char *)&one, sizeof(one)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) log_err_errno("Setting SO_BROADCAST error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) if (args->dev && bind_to_device(sd, args->dev) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) else if (args->use_setsockopt &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) set_multicast_if(sd, args->ifindex))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) laddr.sin_addr.s_addr = if_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) if (bind(sd, (struct sockaddr *) &laddr, sizeof(laddr)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) log_err_errno("bind failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) if (server &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) set_membership(sd, args->grp.s_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) args->local_addr.in.s_addr, args->ifindex))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) return sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) close(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) static int msock_server(struct sock_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) return msock_init(args, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) static int msock_client(struct sock_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) return msock_init(args, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) static int bind_socket(int sd, struct sock_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) struct sockaddr_in serv_addr = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) .sin_family = AF_INET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) struct sockaddr_in6 serv6_addr = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) .sin6_family = AF_INET6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) void *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) socklen_t alen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) if (!args->has_local_ip && args->type == SOCK_RAW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) switch (args->version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) case AF_INET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) serv_addr.sin_port = htons(args->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) serv_addr.sin_addr = args->local_addr.in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) addr = &serv_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) alen = sizeof(serv_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) case AF_INET6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) serv6_addr.sin6_port = htons(args->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) serv6_addr.sin6_addr = args->local_addr.in6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) addr = &serv6_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) alen = sizeof(serv6_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) log_error("Invalid address family\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (bind(sd, addr, alen) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) log_err_errno("error binding socket");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) static int lsock_init(struct sock_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) int sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) sd = socket(args->version, args->type, args->protocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) if (sd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) log_err_errno("Error opening socket");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) if (set_reuseaddr(sd) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) if (set_reuseport(sd) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) if (args->dev && bind_to_device(sd, args->dev) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) else if (args->use_setsockopt &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) set_unicast_if(sd, args->ifindex, args->version))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) if (bind_socket(sd, args))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) if (args->bind_test_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (args->type == SOCK_STREAM && listen(sd, 1) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) log_err_errno("listen failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) flags = fcntl(sd, F_GETFL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) if ((flags < 0) || (fcntl(sd, F_SETFL, flags|O_NONBLOCK) < 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) log_err_errno("Failed to set non-blocking option");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) if (fcntl(sd, F_SETFD, FD_CLOEXEC) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) log_err_errno("Failed to set close-on-exec flag");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) return sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) close(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) static int do_server(struct sock_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) struct timeval timeout = { .tv_sec = prog_timeout }, *ptval = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) unsigned char addr[sizeof(struct sockaddr_in6)] = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) socklen_t alen = sizeof(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) int lsd, csd = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) fd_set rfds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) if (prog_timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) ptval = &timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) if (args->has_grp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) lsd = msock_server(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) lsd = lsock_init(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) if (lsd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) if (args->bind_test_only) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) close(lsd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) if (args->type != SOCK_STREAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) rc = msg_loop(0, lsd, (void *) addr, alen, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) close(lsd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) if (args->password && tcp_md5_remote(lsd, args)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) close(lsd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) log_msg("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) log_msg("waiting for client connection.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) FD_ZERO(&rfds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) FD_SET(lsd, &rfds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) rc = select(lsd+1, &rfds, NULL, NULL, ptval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) if (rc == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) rc = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) if (errno == EINTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) log_err_errno("select failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) if (FD_ISSET(lsd, &rfds)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) csd = accept(lsd, (void *) addr, &alen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) if (csd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) log_err_errno("accept failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) rc = show_sockstat(csd, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) rc = check_device(csd, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) rc = msg_loop(0, csd, (void *) addr, alen, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) close(csd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) if (!interactive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) close(lsd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) static int wait_for_connect(int sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) struct timeval _tv = { .tv_sec = prog_timeout }, *tv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) fd_set wfd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) int val = 0, sz = sizeof(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) FD_ZERO(&wfd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) FD_SET(sd, &wfd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) if (prog_timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) tv = &_tv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) rc = select(FD_SETSIZE, NULL, &wfd, NULL, tv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) if (rc == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) log_error("connect timed out\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) return -2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) } else if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) log_err_errno("select failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) return -3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) if (getsockopt(sd, SOL_SOCKET, SO_ERROR, &val, (socklen_t *)&sz) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) log_err_errno("getsockopt(SO_ERROR) failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) return -4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) if (val != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) log_error("connect failed: %d: %s\n", val, strerror(val));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) static int connectsock(void *addr, socklen_t alen, struct sock_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) int sd, rc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) sd = socket(args->version, args->type, args->protocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) if (sd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) log_err_errno("Failed to create socket");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) flags = fcntl(sd, F_GETFL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) if ((flags < 0) || (fcntl(sd, F_SETFL, flags|O_NONBLOCK) < 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) log_err_errno("Failed to set non-blocking option");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) if (set_reuseport(sd) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) if (args->dev && bind_to_device(sd, args->dev) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) else if (args->use_setsockopt &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) set_unicast_if(sd, args->ifindex, args->version))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) if (args->has_local_ip && bind_socket(sd, args))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) if (args->type != SOCK_STREAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) if (args->password && tcp_md5sig(sd, addr, alen, args))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) if (args->bind_test_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) if (connect(sd, addr, alen) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) if (errno != EINPROGRESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) log_err_errno("Failed to connect to remote host");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) rc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) rc = wait_for_connect(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) return sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) close(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) static int do_client(struct sock_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) struct sockaddr_in sin = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) .sin_family = AF_INET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) struct sockaddr_in6 sin6 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) .sin6_family = AF_INET6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) void *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) int alen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) int sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) if (!args->has_remote_ip && !args->has_grp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) fprintf(stderr, "remote IP or multicast group not given\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) switch (args->version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) case AF_INET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) sin.sin_port = htons(args->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) if (args->has_grp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) sin.sin_addr = args->grp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) sin.sin_addr = args->remote_addr.in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) addr = &sin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) alen = sizeof(sin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) case AF_INET6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) sin6.sin6_port = htons(args->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) sin6.sin6_addr = args->remote_addr.in6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) sin6.sin6_scope_id = args->scope_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) addr = &sin6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) alen = sizeof(sin6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) if (args->has_grp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) sd = msock_client(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) sd = connectsock(addr, alen, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) if (sd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) return -sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) if (args->bind_test_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) if (args->type == SOCK_STREAM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) rc = show_sockstat(sd, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) if (rc != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) rc = msg_loop(1, sd, addr, alen, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) close(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) enum addr_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) ADDR_TYPE_LOCAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) ADDR_TYPE_REMOTE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) ADDR_TYPE_MCAST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) ADDR_TYPE_EXPECTED_LOCAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) ADDR_TYPE_EXPECTED_REMOTE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) ADDR_TYPE_MD5_PREFIX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) static int convert_addr(struct sock_args *args, const char *_str,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) enum addr_type atype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) int pfx_len_max = args->version == AF_INET6 ? 128 : 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) int family = args->version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) char *str, *dev, *sep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) struct in6_addr *in6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) struct in_addr *in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) const char *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) void *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) str = strdup(_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) if (!str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) switch (atype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) case ADDR_TYPE_LOCAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) desc = "local";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) addr = &args->local_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) case ADDR_TYPE_REMOTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) desc = "remote";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) addr = &args->remote_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) case ADDR_TYPE_MCAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) desc = "mcast grp";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) addr = &args->grp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) case ADDR_TYPE_EXPECTED_LOCAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) desc = "expected local";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) addr = &args->expected_laddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) case ADDR_TYPE_EXPECTED_REMOTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) desc = "expected remote";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) addr = &args->expected_raddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) case ADDR_TYPE_MD5_PREFIX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) desc = "md5 prefix";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) if (family == AF_INET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) args->md5_prefix.v4.sin_family = AF_INET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) addr = &args->md5_prefix.v4.sin_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) } else if (family == AF_INET6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) args->md5_prefix.v6.sin6_family = AF_INET6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) addr = &args->md5_prefix.v6.sin6_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) sep = strchr(str, '/');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) if (sep) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) *sep = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) sep++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) if (str_to_uint(sep, 1, pfx_len_max,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) &args->prefix_len) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) fprintf(stderr, "Invalid port\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) args->prefix_len = pfx_len_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) log_error("unknown address type");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) switch (family) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) case AF_INET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) in = (struct in_addr *) addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) if (str) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) if (inet_pton(AF_INET, str, in) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) log_error("Invalid %s IP address\n", desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) rc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) in->s_addr = htonl(INADDR_ANY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) case AF_INET6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) dev = strchr(str, '%');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) if (dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) *dev = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) dev++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) in6 = (struct in6_addr *) addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) if (str) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) if (inet_pton(AF_INET6, str, in6) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) log_error("Invalid %s IPv6 address\n", desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) rc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) *in6 = in6addr_any;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) if (dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) args->scope_id = get_ifidx(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) if (args->scope_id < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) log_error("Invalid scope on %s IPv6 address\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) rc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) log_error("Invalid address family\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) free(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) static char *random_msg(int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) int i, n = 0, olen = len + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) char *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) if (len <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) m = malloc(olen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) if (!m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) while (len > 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) i = snprintf(m + n, olen - n, "%.26s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) "abcdefghijklmnopqrstuvwxyz");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) n += i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) len -= i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) i = snprintf(m + n, olen - n, "%.*s", len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) "abcdefghijklmnopqrstuvwxyz");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) return m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) #define GETOPT_STR "sr:l:p:t:g:P:DRn:M:m:d:SCi6L:0:1:2:Fbq"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) static void print_usage(char *prog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) printf(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) "usage: %s OPTS\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) "Required:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) " -r addr remote address to connect to (client mode only)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) " -p port port to connect to (client mode)/listen on (server mode)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) " (default: %d)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) " -s server mode (default: client mode)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) " -t timeout seconds (default: none)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) "Optional:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) " -F Restart server loop\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) " -6 IPv6 (default is IPv4)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) " -P proto protocol for socket: icmp, ospf (default: none)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) " -D|R datagram (D) / raw (R) socket (default stream)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) " -l addr local address to bind to\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) " -d dev bind socket to given device name\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) " -S use setsockopt (IP_UNICAST_IF or IP_MULTICAST_IF)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) " to set device binding\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) " -C use cmsg and IP_PKTINFO to specify device binding\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) " -L len send random message of given length\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) " -n num number of times to send message\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) " -M password use MD5 sum protection\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) " -m prefix/len prefix and length to use for MD5 key\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) " -g grp multicast group (e.g., 239.1.1.1)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) " -i interactive mode (default is echo and terminate)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) " -0 addr Expected local address\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) " -1 addr Expected remote address\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) " -2 dev Expected device name (or index) to receive packet\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) " -b Bind test only.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) " -q Be quiet. Run test without printing anything.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) , prog, DEFAULT_PORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) int main(int argc, char *argv[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) struct sock_args args = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) .version = AF_INET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) .type = SOCK_STREAM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) .port = DEFAULT_PORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) struct protoent *pe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) unsigned int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) int forever = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) /* process inputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) extern char *optarg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) * process input args
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) while ((rc = getopt(argc, argv, GETOPT_STR)) != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) switch (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) server_mode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) case 'F':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) forever = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) case 'l':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) args.has_local_ip = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) if (convert_addr(&args, optarg, ADDR_TYPE_LOCAL) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) case 'r':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) args.has_remote_ip = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) if (convert_addr(&args, optarg, ADDR_TYPE_REMOTE) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) case 'p':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) if (str_to_uint(optarg, 1, 65535, &tmp) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) fprintf(stderr, "Invalid port\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) args.port = (unsigned short) tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) case 't':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) if (str_to_uint(optarg, 0, INT_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) &prog_timeout) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) fprintf(stderr, "Invalid timeout\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) case 'D':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) args.type = SOCK_DGRAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) case 'R':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) args.type = SOCK_RAW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) args.port = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) if (!args.protocol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) args.protocol = IPPROTO_RAW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) case 'P':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) pe = getprotobyname(optarg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) if (pe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) args.protocol = pe->p_proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) if (str_to_uint(optarg, 0, 0xffff, &tmp) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) fprintf(stderr, "Invalid protocol\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) args.protocol = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) case 'n':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) iter = atoi(optarg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) case 'L':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) msg = random_msg(atoi(optarg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) case 'M':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) args.password = optarg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) case 'm':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) if (convert_addr(&args, optarg, ADDR_TYPE_MD5_PREFIX) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) case 'S':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) args.use_setsockopt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) case 'C':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) args.use_cmsg = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) case 'd':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) args.dev = optarg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) args.ifindex = get_ifidx(optarg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) if (args.ifindex < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) fprintf(stderr, "Invalid device name\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) case 'i':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) interactive = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) case 'g':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) args.has_grp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) if (convert_addr(&args, optarg, ADDR_TYPE_MCAST) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) args.type = SOCK_DGRAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) case '6':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) args.version = AF_INET6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) case 'b':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) args.bind_test_only = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) case '0':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) args.has_expected_laddr = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) if (convert_addr(&args, optarg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) ADDR_TYPE_EXPECTED_LOCAL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) case '1':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) args.has_expected_raddr = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) if (convert_addr(&args, optarg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) ADDR_TYPE_EXPECTED_REMOTE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) case '2':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) if (str_to_uint(optarg, 0, INT_MAX, &tmp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) args.expected_ifindex = (int)tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) args.expected_ifindex = get_ifidx(optarg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) if (args.expected_ifindex < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) fprintf(stderr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) "Invalid expected device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) case 'q':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) quiet = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) print_usage(argv[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) if (args.password &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) ((!args.has_remote_ip && !args.prefix_len) || args.type != SOCK_STREAM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) log_error("MD5 passwords apply to TCP only and require a remote ip for the password\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) if (args.prefix_len && !args.password) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) log_error("Prefix range for MD5 protection specified without a password\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) if ((args.use_setsockopt || args.use_cmsg) && !args.ifindex) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) fprintf(stderr, "Device binding not specified\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) if (args.use_setsockopt || args.use_cmsg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) args.dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) if (iter == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) fprintf(stderr, "Invalid number of messages to send\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) if (args.type == SOCK_STREAM && !args.protocol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) args.protocol = IPPROTO_TCP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) if (args.type == SOCK_DGRAM && !args.protocol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) args.protocol = IPPROTO_UDP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) if ((args.type == SOCK_STREAM || args.type == SOCK_DGRAM) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) args.port == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) fprintf(stderr, "Invalid port number\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) if (!server_mode && !args.has_grp &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) !args.has_remote_ip && !args.has_local_ip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) fprintf(stderr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) "Local (server mode) or remote IP (client IP) required\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) if (interactive) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) prog_timeout = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) msg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) if (server_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) rc = do_server(&args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) } while (forever);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) return do_client(&args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) }