brintos

brintos / linux-shallow public Read only

0
0
Text · 46.1 KiB · cd8a580 Raw
2255 lines · c
1// SPDX-License-Identifier: GPL-2.02/* nettest - used for functional tests of networking APIs3 *4 * Copyright (c) 2013-2019 David Ahern <dsahern@gmail.com>. All rights reserved.5 */6 7#define _GNU_SOURCE8#include <features.h>9#include <sys/types.h>10#include <sys/ioctl.h>11#include <sys/socket.h>12#include <sys/wait.h>13#include <linux/tcp.h>14#include <linux/udp.h>15#include <arpa/inet.h>16#include <net/if.h>17#include <netinet/in.h>18#include <netinet/ip.h>19#include <netdb.h>20#include <fcntl.h>21#include <libgen.h>22#include <limits.h>23#include <sched.h>24#include <stdarg.h>25#include <stdio.h>26#include <stdlib.h>27#include <string.h>28#include <unistd.h>29#include <time.h>30#include <errno.h>31#include <getopt.h>32 33#include <linux/xfrm.h>34#include <linux/ipsec.h>35#include <linux/pfkeyv2.h>36 37#ifndef IPV6_UNICAST_IF38#define IPV6_UNICAST_IF         7639#endif40#ifndef IPV6_MULTICAST_IF41#define IPV6_MULTICAST_IF       1742#endif43 44#define DEFAULT_PORT 1234545 46#define NS_PREFIX "/run/netns/"47 48#ifndef MAX49#define MAX(a, b)  ((a) > (b) ? (a) : (b))50#endif51#ifndef MIN52#define MIN(a, b)  ((a) < (b) ? (a) : (b))53#endif54 55struct sock_args {56	/* local address */57	const char *local_addr_str;58	const char *client_local_addr_str;59	union {60		struct in_addr  in;61		struct in6_addr in6;62	} local_addr;63 64	/* remote address */65	const char *remote_addr_str;66	union {67		struct in_addr  in;68		struct in6_addr in6;69	} remote_addr;70	int scope_id;  /* remote scope; v6 send only */71 72	struct in_addr grp;     /* multicast group */73 74	unsigned int has_local_ip:1,75		     has_remote_ip:1,76		     has_grp:1,77		     has_expected_laddr:1,78		     has_expected_raddr:1,79		     bind_test_only:1,80		     client_dontroute:1,81		     server_dontroute:1;82 83	unsigned short port;84 85	int type;      /* DGRAM, STREAM, RAW */86	int protocol;87	int version;   /* AF_INET/AF_INET6 */88 89	int use_setsockopt;90	int use_freebind;91	int use_cmsg;92	uint8_t dsfield;93	const char *dev;94	const char *server_dev;95	int ifindex;96 97	const char *clientns;98	const char *serverns;99 100	const char *password;101	const char *client_pw;102	/* prefix for MD5 password */103	const char *md5_prefix_str;104	union {105		struct sockaddr_in v4;106		struct sockaddr_in6 v6;107	} md5_prefix;108	unsigned int prefix_len;109	/* 0: default, -1: force off, +1: force on */110	int bind_key_ifindex;111 112	/* expected addresses and device index for connection */113	const char *expected_dev;114	const char *expected_server_dev;115	int expected_ifindex;116 117	/* local address */118	const char *expected_laddr_str;119	union {120		struct in_addr  in;121		struct in6_addr in6;122	} expected_laddr;123 124	/* remote address */125	const char *expected_raddr_str;126	union {127		struct in_addr  in;128		struct in6_addr in6;129	} expected_raddr;130 131	/* ESP in UDP encap test */132	int use_xfrm;133 134	/* use send() and connect() instead of sendto */135	int datagram_connect;136};137 138static int server_mode;139static unsigned int prog_timeout = 5;140static unsigned int interactive;141static int iter = 1;142static char *msg = "Hello world!";143static int msglen;144static int quiet;145static int try_broadcast = 1;146 147static char *timestamp(char *timebuf, int buflen)148{149	time_t now;150 151	now = time(NULL);152	if (strftime(timebuf, buflen, "%T", localtime(&now)) == 0) {153		memset(timebuf, 0, buflen);154		strncpy(timebuf, "00:00:00", buflen-1);155	}156 157	return timebuf;158}159 160static void log_msg(const char *format, ...)161{162	char timebuf[64];163	va_list args;164 165	if (quiet)166		return;167 168	fprintf(stdout, "%s %s:",169		timestamp(timebuf, sizeof(timebuf)),170		server_mode ? "server" : "client");171	va_start(args, format);172	vfprintf(stdout, format, args);173	va_end(args);174 175	fflush(stdout);176}177 178static void log_error(const char *format, ...)179{180	char timebuf[64];181	va_list args;182 183	if (quiet)184		return;185 186	fprintf(stderr, "%s %s:",187		timestamp(timebuf, sizeof(timebuf)),188		server_mode ? "server" : "client");189	va_start(args, format);190	vfprintf(stderr, format, args);191	va_end(args);192 193	fflush(stderr);194}195 196static void log_err_errno(const char *fmt, ...)197{198	char timebuf[64];199	va_list args;200 201	if (quiet)202		return;203 204	fprintf(stderr, "%s %s: ",205		timestamp(timebuf, sizeof(timebuf)),206		server_mode ? "server" : "client");207	va_start(args, fmt);208	vfprintf(stderr, fmt, args);209	va_end(args);210 211	fprintf(stderr, ": %d: %s\n", errno, strerror(errno));212	fflush(stderr);213}214 215static void log_address(const char *desc, struct sockaddr *sa)216{217	char addrstr[64];218 219	if (quiet)220		return;221 222	if (sa->sa_family == AF_INET) {223		struct sockaddr_in *s = (struct sockaddr_in *) sa;224 225		log_msg("%s %s:%d\n",226			desc,227			inet_ntop(AF_INET, &s->sin_addr, addrstr,228				  sizeof(addrstr)),229			ntohs(s->sin_port));230 231	} else if (sa->sa_family == AF_INET6) {232		struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sa;233 234		log_msg("%s [%s]:%d\n",235			desc,236			inet_ntop(AF_INET6, &s6->sin6_addr, addrstr,237				  sizeof(addrstr)),238			ntohs(s6->sin6_port));239	}240 241	fflush(stdout);242}243 244static int switch_ns(const char *ns)245{246	char path[PATH_MAX];247	int fd, ret;248 249	if (geteuid())250		log_error("warning: likely need root to set netns %s!\n", ns);251 252	snprintf(path, sizeof(path), "%s%s", NS_PREFIX, ns);253	fd = open(path, 0);254	if (fd < 0) {255		log_err_errno("Failed to open netns path; can not switch netns");256		return 1;257	}258 259	ret = setns(fd, CLONE_NEWNET);260	close(fd);261 262	return ret;263}264 265static int tcp_md5sig(int sd, void *addr, socklen_t alen, struct sock_args *args)266{267	int keylen = strlen(args->password);268	struct tcp_md5sig md5sig = {};269	int opt = TCP_MD5SIG;270	int rc;271 272	md5sig.tcpm_keylen = keylen;273	memcpy(md5sig.tcpm_key, args->password, keylen);274 275	if (args->prefix_len) {276		opt = TCP_MD5SIG_EXT;277		md5sig.tcpm_flags |= TCP_MD5SIG_FLAG_PREFIX;278 279		md5sig.tcpm_prefixlen = args->prefix_len;280		addr = &args->md5_prefix;281	}282	memcpy(&md5sig.tcpm_addr, addr, alen);283 284	if ((args->ifindex && args->bind_key_ifindex >= 0) || args->bind_key_ifindex >= 1) {285		opt = TCP_MD5SIG_EXT;286		md5sig.tcpm_flags |= TCP_MD5SIG_FLAG_IFINDEX;287 288		md5sig.tcpm_ifindex = args->ifindex;289		log_msg("TCP_MD5SIG_FLAG_IFINDEX set tcpm_ifindex=%d\n", md5sig.tcpm_ifindex);290	} else {291		log_msg("TCP_MD5SIG_FLAG_IFINDEX off\n", md5sig.tcpm_ifindex);292	}293 294	rc = setsockopt(sd, IPPROTO_TCP, opt, &md5sig, sizeof(md5sig));295	if (rc < 0) {296		/* ENOENT is harmless. Returned when a password is cleared */297		if (errno == ENOENT)298			rc = 0;299		else300			log_err_errno("setsockopt(TCP_MD5SIG)");301	}302 303	return rc;304}305 306static int tcp_md5_remote(int sd, struct sock_args *args)307{308	struct sockaddr_in sin = {309		.sin_family = AF_INET,310	};311	struct sockaddr_in6 sin6 = {312		.sin6_family = AF_INET6,313	};314	void *addr;315	int alen;316 317	switch (args->version) {318	case AF_INET:319		sin.sin_port = htons(args->port);320		sin.sin_addr = args->md5_prefix.v4.sin_addr;321		addr = &sin;322		alen = sizeof(sin);323		break;324	case AF_INET6:325		sin6.sin6_port = htons(args->port);326		sin6.sin6_addr = args->md5_prefix.v6.sin6_addr;327		addr = &sin6;328		alen = sizeof(sin6);329		break;330	default:331		log_error("unknown address family\n");332		exit(1);333	}334 335	if (tcp_md5sig(sd, addr, alen, args))336		return -1;337 338	return 0;339}340 341static int get_ifidx(const char *ifname)342{343	struct ifreq ifdata;344	int sd, rc;345 346	if (!ifname || *ifname == '\0')347		return -1;348 349	memset(&ifdata, 0, sizeof(ifdata));350 351	strcpy(ifdata.ifr_name, ifname);352 353	sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);354	if (sd < 0) {355		log_err_errno("socket failed");356		return -1;357	}358 359	rc = ioctl(sd, SIOCGIFINDEX, (char *)&ifdata);360	close(sd);361	if (rc != 0) {362		log_err_errno("ioctl(SIOCGIFINDEX) failed");363		return -1;364	}365 366	return ifdata.ifr_ifindex;367}368 369static int bind_to_device(int sd, const char *name)370{371	int rc;372 373	rc = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name)+1);374	if (rc < 0)375		log_err_errno("setsockopt(SO_BINDTODEVICE)");376 377	return rc;378}379 380static int get_bind_to_device(int sd, char *name, size_t len)381{382	int rc;383	socklen_t optlen = len;384 385	name[0] = '\0';386	rc = getsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, name, &optlen);387	if (rc < 0)388		log_err_errno("setsockopt(SO_BINDTODEVICE)");389 390	return rc;391}392 393static int check_device(int sd, struct sock_args *args)394{395	int ifindex = 0;396	char name[32];397 398	if (get_bind_to_device(sd, name, sizeof(name)))399		*name = '\0';400	else401		ifindex = get_ifidx(name);402 403	log_msg("    bound to device %s/%d\n",404		*name ? name : "<none>", ifindex);405 406	if (!args->expected_ifindex)407		return 0;408 409	if (args->expected_ifindex != ifindex) {410		log_error("Device index mismatch: expected %d have %d\n",411			  args->expected_ifindex, ifindex);412		return 1;413	}414 415	log_msg("Device index matches: expected %d have %d\n",416		args->expected_ifindex, ifindex);417 418	return 0;419}420 421static int set_pktinfo_v4(int sd)422{423	int one = 1;424	int rc;425 426	rc = setsockopt(sd, SOL_IP, IP_PKTINFO, &one, sizeof(one));427	if (rc < 0 && rc != -ENOTSUP)428		log_err_errno("setsockopt(IP_PKTINFO)");429 430	return rc;431}432 433static int set_recvpktinfo_v6(int sd)434{435	int one = 1;436	int rc;437 438	rc = setsockopt(sd, SOL_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));439	if (rc < 0 && rc != -ENOTSUP)440		log_err_errno("setsockopt(IPV6_RECVPKTINFO)");441 442	return rc;443}444 445static int set_recverr_v4(int sd)446{447	int one = 1;448	int rc;449 450	rc = setsockopt(sd, SOL_IP, IP_RECVERR, &one, sizeof(one));451	if (rc < 0 && rc != -ENOTSUP)452		log_err_errno("setsockopt(IP_RECVERR)");453 454	return rc;455}456 457static int set_recverr_v6(int sd)458{459	int one = 1;460	int rc;461 462	rc = setsockopt(sd, SOL_IPV6, IPV6_RECVERR, &one, sizeof(one));463	if (rc < 0 && rc != -ENOTSUP)464		log_err_errno("setsockopt(IPV6_RECVERR)");465 466	return rc;467}468 469static int set_unicast_if(int sd, int ifindex, int version)470{471	int opt = IP_UNICAST_IF;472	int level = SOL_IP;473	int rc;474 475	ifindex = htonl(ifindex);476 477	if (version == AF_INET6) {478		opt = IPV6_UNICAST_IF;479		level = SOL_IPV6;480	}481	rc = setsockopt(sd, level, opt, &ifindex, sizeof(ifindex));482	if (rc < 0)483		log_err_errno("setsockopt(IP_UNICAST_IF)");484 485	return rc;486}487 488static int set_multicast_if(int sd, int ifindex)489{490	struct ip_mreqn mreq = { .imr_ifindex = ifindex };491	int rc;492 493	rc = setsockopt(sd, SOL_IP, IP_MULTICAST_IF, &mreq, sizeof(mreq));494	if (rc < 0)495		log_err_errno("setsockopt(IP_MULTICAST_IF)");496 497	return rc;498}499 500static int set_membership(int sd, uint32_t grp, uint32_t addr, int ifindex)501{502	uint32_t if_addr = addr;503	struct ip_mreqn mreq;504	int rc;505 506	if (addr == htonl(INADDR_ANY) && !ifindex) {507		log_error("Either local address or device needs to be given for multicast membership\n");508		return -1;509	}510 511	mreq.imr_multiaddr.s_addr = grp;512	mreq.imr_address.s_addr = if_addr;513	mreq.imr_ifindex = ifindex;514 515	rc = setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));516	if (rc < 0) {517		log_err_errno("setsockopt(IP_ADD_MEMBERSHIP)");518		return -1;519	}520 521	return 0;522}523 524static int set_freebind(int sd, int version)525{526	unsigned int one = 1;527	int rc = 0;528 529	switch (version) {530	case AF_INET:531		if (setsockopt(sd, SOL_IP, IP_FREEBIND, &one, sizeof(one))) {532			log_err_errno("setsockopt(IP_FREEBIND)");533			rc = -1;534		}535		break;536	case AF_INET6:537		if (setsockopt(sd, SOL_IPV6, IPV6_FREEBIND, &one, sizeof(one))) {538			log_err_errno("setsockopt(IPV6_FREEBIND");539			rc = -1;540		}541		break;542	}543 544	return rc;545}546 547static int set_broadcast(int sd)548{549	unsigned int one = 1;550	int rc = 0;551 552	if (setsockopt(sd, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one)) != 0) {553		log_err_errno("setsockopt(SO_BROADCAST)");554		rc = -1;555	}556 557	return rc;558}559 560static int set_reuseport(int sd)561{562	unsigned int one = 1;563	int rc = 0;564 565	if (setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) != 0) {566		log_err_errno("setsockopt(SO_REUSEPORT)");567		rc = -1;568	}569 570	return rc;571}572 573static int set_reuseaddr(int sd)574{575	unsigned int one = 1;576	int rc = 0;577 578	if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) != 0) {579		log_err_errno("setsockopt(SO_REUSEADDR)");580		rc = -1;581	}582 583	return rc;584}585 586static int set_dsfield(int sd, int version, int dsfield)587{588	if (!dsfield)589		return 0;590 591	switch (version) {592	case AF_INET:593		if (setsockopt(sd, SOL_IP, IP_TOS, &dsfield,594			       sizeof(dsfield)) < 0) {595			log_err_errno("setsockopt(IP_TOS)");596			return -1;597		}598		break;599 600	case AF_INET6:601		if (setsockopt(sd, SOL_IPV6, IPV6_TCLASS, &dsfield,602			       sizeof(dsfield)) < 0) {603			log_err_errno("setsockopt(IPV6_TCLASS)");604			return -1;605		}606		break;607 608	default:609		log_error("Invalid address family\n");610		return -1;611	}612 613	return 0;614}615 616static int set_dontroute(int sd)617{618	unsigned int one = 1;619 620	if (setsockopt(sd, SOL_SOCKET, SO_DONTROUTE, &one, sizeof(one)) < 0) {621		log_err_errno("setsockopt(SO_DONTROUTE)");622		return -1;623	}624 625	return 0;626}627 628static int str_to_uint(const char *str, int min, int max, unsigned int *value)629{630	int number;631	char *end;632 633	errno = 0;634	number = (unsigned int) strtoul(str, &end, 0);635 636	/* entire string should be consumed by conversion637	 * and value should be between min and max638	 */639	if (((*end == '\0') || (*end == '\n')) && (end != str) &&640	    (errno != ERANGE) && (min <= number) && (number <= max)) {641		*value = number;642		return 0;643	}644 645	return -1;646}647 648static int resolve_devices(struct sock_args *args)649{650	if (args->dev) {651		args->ifindex = get_ifidx(args->dev);652		if (args->ifindex < 0) {653			log_error("Invalid device name\n");654			return 1;655		}656	}657 658	if (args->expected_dev) {659		unsigned int tmp;660 661		if (str_to_uint(args->expected_dev, 0, INT_MAX, &tmp) == 0) {662			args->expected_ifindex = (int)tmp;663		} else {664			args->expected_ifindex = get_ifidx(args->expected_dev);665			if (args->expected_ifindex < 0) {666				fprintf(stderr, "Invalid expected device\n");667				return 1;668			}669		}670	}671 672	return 0;673}674 675static int expected_addr_match(struct sockaddr *sa, void *expected,676			       const char *desc)677{678	char addrstr[64];679	int rc = 0;680 681	if (sa->sa_family == AF_INET) {682		struct sockaddr_in *s = (struct sockaddr_in *) sa;683		struct in_addr *exp_in = (struct in_addr *) expected;684 685		if (s->sin_addr.s_addr != exp_in->s_addr) {686			log_error("%s address does not match expected %s\n",687				  desc,688				  inet_ntop(AF_INET, exp_in,689					    addrstr, sizeof(addrstr)));690			rc = 1;691		}692	} else if (sa->sa_family == AF_INET6) {693		struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sa;694		struct in6_addr *exp_in = (struct in6_addr *) expected;695 696		if (memcmp(&s6->sin6_addr, exp_in, sizeof(*exp_in))) {697			log_error("%s address does not match expected %s\n",698				  desc,699				  inet_ntop(AF_INET6, exp_in,700					    addrstr, sizeof(addrstr)));701			rc = 1;702		}703	} else {704		log_error("%s address does not match expected - unknown family\n",705			  desc);706		rc = 1;707	}708 709	if (!rc)710		log_msg("%s address matches expected\n", desc);711 712	return rc;713}714 715static int show_sockstat(int sd, struct sock_args *args)716{717	struct sockaddr_in6 local_addr, remote_addr;718	socklen_t alen = sizeof(local_addr);719	struct sockaddr *sa;720	const char *desc;721	int rc = 0;722 723	desc = server_mode ? "server local:" : "client local:";724	sa = (struct sockaddr *) &local_addr;725	if (getsockname(sd, sa, &alen) == 0) {726		log_address(desc, sa);727 728		if (args->has_expected_laddr) {729			rc = expected_addr_match(sa, &args->expected_laddr,730						 "local");731		}732	} else {733		log_err_errno("getsockname failed");734	}735 736	sa = (struct sockaddr *) &remote_addr;737	desc = server_mode ? "server peer:" : "client peer:";738	if (getpeername(sd, sa, &alen) == 0) {739		log_address(desc, sa);740 741		if (args->has_expected_raddr) {742			rc |= expected_addr_match(sa, &args->expected_raddr,743						 "remote");744		}745	} else {746		log_err_errno("getpeername failed");747	}748 749	return rc;750}751 752enum addr_type {753	ADDR_TYPE_LOCAL,754	ADDR_TYPE_REMOTE,755	ADDR_TYPE_MCAST,756	ADDR_TYPE_EXPECTED_LOCAL,757	ADDR_TYPE_EXPECTED_REMOTE,758	ADDR_TYPE_MD5_PREFIX,759};760 761static int convert_addr(struct sock_args *args, const char *_str,762			enum addr_type atype)763{764	int pfx_len_max = args->version == AF_INET6 ? 128 : 32;765	int family = args->version;766	char *str, *dev, *sep;767	struct in6_addr *in6;768	struct in_addr  *in;769	const char *desc;770	void *addr;771	int rc = 0;772 773	str = strdup(_str);774	if (!str)775		return -ENOMEM;776 777	switch (atype) {778	case ADDR_TYPE_LOCAL:779		desc = "local";780		addr = &args->local_addr;781		break;782	case ADDR_TYPE_REMOTE:783		desc = "remote";784		addr = &args->remote_addr;785		break;786	case ADDR_TYPE_MCAST:787		desc = "mcast grp";788		addr = &args->grp;789		break;790	case ADDR_TYPE_EXPECTED_LOCAL:791		desc = "expected local";792		addr = &args->expected_laddr;793		break;794	case ADDR_TYPE_EXPECTED_REMOTE:795		desc = "expected remote";796		addr = &args->expected_raddr;797		break;798	case ADDR_TYPE_MD5_PREFIX:799		desc = "md5 prefix";800		if (family == AF_INET) {801			args->md5_prefix.v4.sin_family = AF_INET;802			addr = &args->md5_prefix.v4.sin_addr;803		} else if (family == AF_INET6) {804			args->md5_prefix.v6.sin6_family = AF_INET6;805			addr = &args->md5_prefix.v6.sin6_addr;806		} else807			return 1;808 809		sep = strchr(str, '/');810		if (sep) {811			*sep = '\0';812			sep++;813			if (str_to_uint(sep, 1, pfx_len_max,814					&args->prefix_len) != 0) {815				fprintf(stderr, "Invalid port\n");816				return 1;817			}818		} else {819			args->prefix_len = 0;820		}821		break;822	default:823		log_error("unknown address type\n");824		exit(1);825	}826 827	switch (family) {828	case AF_INET:829		in  = (struct in_addr *) addr;830		if (str) {831			if (inet_pton(AF_INET, str, in) == 0) {832				log_error("Invalid %s IP address\n", desc);833				rc = -1;834				goto out;835			}836		} else {837			in->s_addr = htonl(INADDR_ANY);838		}839		break;840 841	case AF_INET6:842		dev = strchr(str, '%');843		if (dev) {844			*dev = '\0';845			dev++;846		}847 848		in6 = (struct in6_addr *) addr;849		if (str) {850			if (inet_pton(AF_INET6, str, in6) == 0) {851				log_error("Invalid %s IPv6 address\n", desc);852				rc = -1;853				goto out;854			}855		} else {856			*in6 = in6addr_any;857		}858		if (dev) {859			args->scope_id = get_ifidx(dev);860			if (args->scope_id < 0) {861				log_error("Invalid scope on %s IPv6 address\n",862					  desc);863				rc = -1;864				goto out;865			}866		}867		break;868 869	default:870		log_error("Invalid address family\n");871	}872 873out:874	free(str);875	return rc;876}877 878static int validate_addresses(struct sock_args *args)879{880	if (args->local_addr_str &&881	    convert_addr(args, args->local_addr_str, ADDR_TYPE_LOCAL) < 0)882		return 1;883 884	if (args->remote_addr_str &&885	    convert_addr(args, args->remote_addr_str, ADDR_TYPE_REMOTE) < 0)886		return 1;887 888	if (args->md5_prefix_str &&889	    convert_addr(args, args->md5_prefix_str,890			 ADDR_TYPE_MD5_PREFIX) < 0)891		return 1;892 893	if (args->expected_laddr_str &&894	    convert_addr(args, args->expected_laddr_str,895			 ADDR_TYPE_EXPECTED_LOCAL))896		return 1;897 898	if (args->expected_raddr_str &&899	    convert_addr(args, args->expected_raddr_str,900			 ADDR_TYPE_EXPECTED_REMOTE))901		return 1;902 903	return 0;904}905 906static int get_index_from_cmsg(struct msghdr *m)907{908	struct cmsghdr *cm;909	int ifindex = 0;910	char buf[64];911 912	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(m);913	     m->msg_controllen != 0 && cm;914	     cm = (struct cmsghdr *)CMSG_NXTHDR(m, cm)) {915 916		if (cm->cmsg_level == SOL_IP &&917		    cm->cmsg_type == IP_PKTINFO) {918			struct in_pktinfo *pi;919 920			pi = (struct in_pktinfo *)(CMSG_DATA(cm));921			inet_ntop(AF_INET, &pi->ipi_addr, buf, sizeof(buf));922			ifindex = pi->ipi_ifindex;923		} else if (cm->cmsg_level == SOL_IPV6 &&924			   cm->cmsg_type == IPV6_PKTINFO) {925			struct in6_pktinfo *pi6;926 927			pi6 = (struct in6_pktinfo *)(CMSG_DATA(cm));928			inet_ntop(AF_INET6, &pi6->ipi6_addr, buf, sizeof(buf));929			ifindex = pi6->ipi6_ifindex;930		}931	}932 933	if (ifindex) {934		log_msg("    pktinfo: ifindex %d dest addr %s\n",935			ifindex, buf);936	}937	return ifindex;938}939 940static int send_msg_no_cmsg(int sd, void *addr, socklen_t alen)941{942	int err;943 944again:945	err = sendto(sd, msg, msglen, 0, addr, alen);946	if (err < 0) {947		if (errno == EACCES && try_broadcast) {948			try_broadcast = 0;949			if (!set_broadcast(sd))950				goto again;951			errno = EACCES;952		}953 954		log_err_errno("sendto failed");955		return 1;956	}957 958	return 0;959}960 961static int send_msg_cmsg(int sd, void *addr, socklen_t alen,962			 int ifindex, int version)963{964	unsigned char cmsgbuf[64];965	struct iovec iov[2];966	struct cmsghdr *cm;967	struct msghdr m;968	int err;969 970	iov[0].iov_base = msg;971	iov[0].iov_len = msglen;972	m.msg_iov = iov;973	m.msg_iovlen = 1;974	m.msg_name = (caddr_t)addr;975	m.msg_namelen = alen;976 977	memset(cmsgbuf, 0, sizeof(cmsgbuf));978	cm = (struct cmsghdr *)cmsgbuf;979	m.msg_control = (caddr_t)cm;980 981	if (version == AF_INET) {982		struct in_pktinfo *pi;983 984		cm->cmsg_level = SOL_IP;985		cm->cmsg_type = IP_PKTINFO;986		cm->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));987		pi = (struct in_pktinfo *)(CMSG_DATA(cm));988		pi->ipi_ifindex = ifindex;989 990		m.msg_controllen = cm->cmsg_len;991 992	} else if (version == AF_INET6) {993		struct in6_pktinfo *pi6;994 995		cm->cmsg_level = SOL_IPV6;996		cm->cmsg_type = IPV6_PKTINFO;997		cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));998 999		pi6 = (struct in6_pktinfo *)(CMSG_DATA(cm));1000		pi6->ipi6_ifindex = ifindex;1001 1002		m.msg_controllen = cm->cmsg_len;1003	}1004 1005again:1006	err = sendmsg(sd, &m, 0);1007	if (err < 0) {1008		if (errno == EACCES && try_broadcast) {1009			try_broadcast = 0;1010			if (!set_broadcast(sd))1011				goto again;1012			errno = EACCES;1013		}1014 1015		log_err_errno("sendmsg failed");1016		return 1;1017	}1018 1019	return 0;1020}1021 1022 1023static int send_msg(int sd, void *addr, socklen_t alen, struct sock_args *args)1024{1025	if (args->type == SOCK_STREAM) {1026		if (write(sd, msg, msglen) < 0) {1027			log_err_errno("write failed sending msg to peer");1028			return 1;1029		}1030	} else if (args->datagram_connect) {1031		if (send(sd, msg, msglen, 0) < 0) {1032			log_err_errno("send failed sending msg to peer");1033			return 1;1034		}1035	} else if (args->ifindex && args->use_cmsg) {1036		if (send_msg_cmsg(sd, addr, alen, args->ifindex, args->version))1037			return 1;1038	} else {1039		if (send_msg_no_cmsg(sd, addr, alen))1040			return 1;1041	}1042 1043	log_msg("Sent message:\n");1044	log_msg("    %.24s%s\n", msg, msglen > 24 ? " ..." : "");1045 1046	return 0;1047}1048 1049static int socket_read_dgram(int sd, struct sock_args *args)1050{1051	unsigned char addr[sizeof(struct sockaddr_in6)];1052	struct sockaddr *sa = (struct sockaddr *) addr;1053	socklen_t alen = sizeof(addr);1054	struct iovec iov[2];1055	struct msghdr m = {1056		.msg_name = (caddr_t)addr,1057		.msg_namelen = alen,1058		.msg_iov = iov,1059		.msg_iovlen = 1,1060	};1061	unsigned char cmsgbuf[256];1062	struct cmsghdr *cm = (struct cmsghdr *)cmsgbuf;1063	char buf[16*1024];1064	int ifindex;1065	int len;1066 1067	iov[0].iov_base = (caddr_t)buf;1068	iov[0].iov_len = sizeof(buf);1069 1070	memset(cmsgbuf, 0, sizeof(cmsgbuf));1071	m.msg_control = (caddr_t)cm;1072	m.msg_controllen = sizeof(cmsgbuf);1073 1074	len = recvmsg(sd, &m, 0);1075	if (len == 0) {1076		log_msg("peer closed connection.\n");1077		return 0;1078	} else if (len < 0) {1079		log_msg("failed to read message: %d: %s\n",1080			errno, strerror(errno));1081		return -1;1082	}1083 1084	buf[len] = '\0';1085 1086	log_address("Message from:", sa);1087	log_msg("    %.24s%s\n", buf, len > 24 ? " ..." : "");1088 1089	ifindex = get_index_from_cmsg(&m);1090	if (args->expected_ifindex) {1091		if (args->expected_ifindex != ifindex) {1092			log_error("Device index mismatch: expected %d have %d\n",1093				  args->expected_ifindex, ifindex);1094			return -1;1095		}1096		log_msg("Device index matches: expected %d have %d\n",1097			args->expected_ifindex, ifindex);1098	}1099 1100	if (!interactive && server_mode) {1101		if (sa->sa_family == AF_INET6) {1102			struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sa;1103			struct in6_addr *in6 = &s6->sin6_addr;1104 1105			if (IN6_IS_ADDR_V4MAPPED(in6)) {1106				const uint32_t *pa = (uint32_t *) &in6->s6_addr;1107				struct in_addr in4;1108				struct sockaddr_in *sin;1109 1110				sin = (struct sockaddr_in *) addr;1111				pa += 3;1112				in4.s_addr = *pa;1113				sin->sin_addr = in4;1114				sin->sin_family = AF_INET;1115				if (send_msg_cmsg(sd, addr, alen,1116						  ifindex, AF_INET) < 0)1117					goto out_err;1118			}1119		}1120again:1121		iov[0].iov_len = len;1122 1123		if (args->version == AF_INET6) {1124			struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sa;1125 1126			if (args->dev) {1127				/* avoid PKTINFO conflicts with bindtodev */1128				if (sendto(sd, buf, len, 0,1129					   (void *) addr, alen) < 0)1130					goto out_err;1131			} else {1132				/* kernel is allowing scope_id to be set to VRF1133				 * index for LLA. for sends to global address1134				 * reset scope id1135				 */1136				s6->sin6_scope_id = ifindex;1137				if (sendmsg(sd, &m, 0) < 0)1138					goto out_err;1139			}1140		} else {1141			int err;1142 1143			err = sendmsg(sd, &m, 0);1144			if (err < 0) {1145				if (errno == EACCES && try_broadcast) {1146					try_broadcast = 0;1147					if (!set_broadcast(sd))1148						goto again;1149					errno = EACCES;1150				}1151				goto out_err;1152			}1153		}1154		log_msg("Sent message:\n");1155		log_msg("    %.24s%s\n", buf, len > 24 ? " ..." : "");1156	}1157 1158	return 1;1159out_err:1160	log_err_errno("failed to send msg to peer");1161	return -1;1162}1163 1164static int socket_read_stream(int sd)1165{1166	char buf[1024];1167	int len;1168 1169	len = read(sd, buf, sizeof(buf)-1);1170	if (len == 0) {1171		log_msg("client closed connection.\n");1172		return 0;1173	} else if (len < 0) {1174		log_msg("failed to read message\n");1175		return -1;1176	}1177 1178	buf[len] = '\0';1179	log_msg("Incoming message:\n");1180	log_msg("    %.24s%s\n", buf, len > 24 ? " ..." : "");1181 1182	if (!interactive && server_mode) {1183		if (write(sd, buf, len) < 0) {1184			log_err_errno("failed to send buf");1185			return -1;1186		}1187		log_msg("Sent message:\n");1188		log_msg("     %.24s%s\n", buf, len > 24 ? " ..." : "");1189	}1190 1191	return 1;1192}1193 1194static int socket_read(int sd, struct sock_args *args)1195{1196	if (args->type == SOCK_STREAM)1197		return socket_read_stream(sd);1198 1199	return socket_read_dgram(sd, args);1200}1201 1202static int stdin_to_socket(int sd, int type, void *addr, socklen_t alen)1203{1204	char buf[1024];1205	int len;1206 1207	if (fgets(buf, sizeof(buf), stdin) == NULL)1208		return 0;1209 1210	len = strlen(buf);1211	if (type == SOCK_STREAM) {1212		if (write(sd, buf, len) < 0) {1213			log_err_errno("failed to send buf");1214			return -1;1215		}1216	} else {1217		int err;1218 1219again:1220		err = sendto(sd, buf, len, 0, addr, alen);1221		if (err < 0) {1222			if (errno == EACCES && try_broadcast) {1223				try_broadcast = 0;1224				if (!set_broadcast(sd))1225					goto again;1226				errno = EACCES;1227			}1228			log_err_errno("failed to send msg to peer");1229			return -1;1230		}1231	}1232	log_msg("Sent message:\n");1233	log_msg("    %.24s%s\n", buf, len > 24 ? " ..." : "");1234 1235	return 1;1236}1237 1238static void set_recv_attr(int sd, int version)1239{1240	if (version == AF_INET6) {1241		set_recvpktinfo_v6(sd);1242		set_recverr_v6(sd);1243	} else {1244		set_pktinfo_v4(sd);1245		set_recverr_v4(sd);1246	}1247}1248 1249static int msg_loop(int client, int sd, void *addr, socklen_t alen,1250		    struct sock_args *args)1251{1252	struct timeval timeout = { .tv_sec = prog_timeout }, *ptval = NULL;1253	fd_set rfds;1254	int nfds;1255	int rc;1256 1257	if (args->type != SOCK_STREAM)1258		set_recv_attr(sd, args->version);1259 1260	if (msg) {1261		msglen = strlen(msg);1262 1263		/* client sends first message */1264		if (client) {1265			if (send_msg(sd, addr, alen, args))1266				return 1;1267		}1268		if (!interactive) {1269			ptval = &timeout;1270			if (!prog_timeout)1271				timeout.tv_sec = 5;1272		}1273	}1274 1275	nfds = interactive ? MAX(fileno(stdin), sd)  + 1 : sd + 1;1276	while (1) {1277		FD_ZERO(&rfds);1278		FD_SET(sd, &rfds);1279		if (interactive)1280			FD_SET(fileno(stdin), &rfds);1281 1282		rc = select(nfds, &rfds, NULL, NULL, ptval);1283		if (rc < 0) {1284			if (errno == EINTR)1285				continue;1286 1287			rc = 1;1288			log_err_errno("select failed");1289			break;1290		} else if (rc == 0) {1291			log_error("Timed out waiting for response\n");1292			rc = 2;1293			break;1294		}1295 1296		if (FD_ISSET(sd, &rfds)) {1297			rc = socket_read(sd, args);1298			if (rc < 0) {1299				rc = 1;1300				break;1301			}1302			if (rc == 0)1303				break;1304		}1305 1306		rc = 0;1307 1308		if (FD_ISSET(fileno(stdin), &rfds)) {1309			if (stdin_to_socket(sd, args->type, addr, alen) <= 0)1310				break;1311		}1312 1313		if (interactive)1314			continue;1315 1316		if (iter != -1) {1317			--iter;1318			if (iter == 0)1319				break;1320		}1321 1322		log_msg("Going into quiet mode\n");1323		quiet = 1;1324 1325		if (client) {1326			if (send_msg(sd, addr, alen, args)) {1327				rc = 1;1328				break;1329			}1330		}1331	}1332 1333	return rc;1334}1335 1336static int msock_init(struct sock_args *args, int server)1337{1338	uint32_t if_addr = htonl(INADDR_ANY);1339	struct sockaddr_in laddr = {1340		.sin_family = AF_INET,1341		.sin_port = htons(args->port),1342	};1343	int one = 1;1344	int sd;1345 1346	if (!server && args->has_local_ip)1347		if_addr = args->local_addr.in.s_addr;1348 1349	sd = socket(PF_INET, SOCK_DGRAM, 0);1350	if (sd < 0) {1351		log_err_errno("socket");1352		return -1;1353	}1354 1355	if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR,1356		       (char *)&one, sizeof(one)) < 0) {1357		log_err_errno("Setting SO_REUSEADDR error");1358		goto out_err;1359	}1360 1361	if (setsockopt(sd, SOL_SOCKET, SO_BROADCAST,1362		       (char *)&one, sizeof(one)) < 0)1363		log_err_errno("Setting SO_BROADCAST error");1364 1365	if (set_dsfield(sd, AF_INET, args->dsfield) != 0)1366		goto out_err;1367 1368	if (server) {1369		if (args->server_dontroute && set_dontroute(sd) != 0)1370			goto out_err;1371	} else {1372		if (args->client_dontroute && set_dontroute(sd) != 0)1373			goto out_err;1374	}1375 1376	if (args->dev && bind_to_device(sd, args->dev) != 0)1377		goto out_err;1378	else if (args->use_setsockopt &&1379		 set_multicast_if(sd, args->ifindex))1380		goto out_err;1381 1382	laddr.sin_addr.s_addr = if_addr;1383 1384	if (bind(sd, (struct sockaddr *) &laddr, sizeof(laddr)) < 0) {1385		log_err_errno("bind failed");1386		goto out_err;1387	}1388 1389	if (server &&1390	    set_membership(sd, args->grp.s_addr,1391			   args->local_addr.in.s_addr, args->ifindex))1392		goto out_err;1393 1394	return sd;1395out_err:1396	close(sd);1397	return -1;1398}1399 1400static int msock_server(struct sock_args *args)1401{1402	return msock_init(args, 1);1403}1404 1405static int msock_client(struct sock_args *args)1406{1407	return msock_init(args, 0);1408}1409 1410static int bind_socket(int sd, struct sock_args *args)1411{1412	struct sockaddr_in serv_addr = {1413		.sin_family = AF_INET,1414	};1415	struct sockaddr_in6 serv6_addr = {1416		.sin6_family = AF_INET6,1417	};1418	void *addr;1419	socklen_t alen;1420 1421	if (!args->has_local_ip && args->type == SOCK_RAW)1422		return 0;1423 1424	switch (args->version) {1425	case AF_INET:1426		serv_addr.sin_port = htons(args->port);1427		serv_addr.sin_addr = args->local_addr.in;1428		addr = &serv_addr;1429		alen = sizeof(serv_addr);1430		break;1431 1432	case AF_INET6:1433		serv6_addr.sin6_port = htons(args->port);1434		serv6_addr.sin6_addr = args->local_addr.in6;1435		addr = &serv6_addr;1436		alen = sizeof(serv6_addr);1437		break;1438 1439	default:1440		log_error("Invalid address family\n");1441		return -1;1442	}1443 1444	if (bind(sd, addr, alen) < 0) {1445		log_err_errno("error binding socket");1446		return -1;1447	}1448 1449	return 0;1450}1451 1452static int config_xfrm_policy(int sd, struct sock_args *args)1453{1454	struct xfrm_userpolicy_info policy = {};1455	int type = UDP_ENCAP_ESPINUDP;1456	int xfrm_af = IP_XFRM_POLICY;1457	int level = SOL_IP;1458 1459	if (args->type != SOCK_DGRAM) {1460		log_error("Invalid socket type. Only DGRAM could be used for XFRM\n");1461		return 1;1462	}1463 1464	policy.action = XFRM_POLICY_ALLOW;1465	policy.sel.family = args->version;1466	if (args->version == AF_INET6) {1467		xfrm_af = IPV6_XFRM_POLICY;1468		level = SOL_IPV6;1469	}1470 1471	policy.dir = XFRM_POLICY_OUT;1472	if (setsockopt(sd, level, xfrm_af, &policy, sizeof(policy)) < 0)1473		return 1;1474 1475	policy.dir = XFRM_POLICY_IN;1476	if (setsockopt(sd, level, xfrm_af, &policy, sizeof(policy)) < 0)1477		return 1;1478 1479	if (setsockopt(sd, IPPROTO_UDP, UDP_ENCAP, &type, sizeof(type)) < 0) {1480		log_err_errno("Failed to set xfrm encap");1481		return 1;1482	}1483 1484	return 0;1485}1486 1487static int lsock_init(struct sock_args *args)1488{1489	long flags;1490	int sd;1491 1492	sd = socket(args->version, args->type, args->protocol);1493	if (sd < 0) {1494		log_err_errno("Error opening socket");1495		return  -1;1496	}1497 1498	if (set_reuseaddr(sd) != 0)1499		goto err;1500 1501	if (set_reuseport(sd) != 0)1502		goto err;1503 1504	if (set_dsfield(sd, args->version, args->dsfield) != 0)1505		goto err;1506 1507	if (args->server_dontroute && set_dontroute(sd) != 0)1508		goto err;1509 1510	if (args->dev && bind_to_device(sd, args->dev) != 0)1511		goto err;1512	else if (args->use_setsockopt &&1513		 set_unicast_if(sd, args->ifindex, args->version))1514		goto err;1515 1516	if (args->use_freebind && set_freebind(sd, args->version))1517		goto err;1518 1519	if (bind_socket(sd, args))1520		goto err;1521 1522	if (args->bind_test_only)1523		goto out;1524 1525	if (args->type == SOCK_STREAM && listen(sd, 1) < 0) {1526		log_err_errno("listen failed");1527		goto err;1528	}1529 1530	flags = fcntl(sd, F_GETFL);1531	if ((flags < 0) || (fcntl(sd, F_SETFL, flags|O_NONBLOCK) < 0)) {1532		log_err_errno("Failed to set non-blocking option");1533		goto err;1534	}1535 1536	if (fcntl(sd, F_SETFD, FD_CLOEXEC) < 0)1537		log_err_errno("Failed to set close-on-exec flag");1538 1539	if (args->use_xfrm && config_xfrm_policy(sd, args)) {1540		log_err_errno("Failed to set xfrm policy");1541		goto err;1542	}1543 1544out:1545	return sd;1546 1547err:1548	close(sd);1549	return -1;1550}1551 1552static void ipc_write(int fd, int message)1553{1554	/* Not in both_mode, so there's no process to signal */1555	if (fd < 0)1556		return;1557 1558	if (write(fd, &message, sizeof(message)) < 0)1559		log_err_errno("Failed to send client status");1560}1561 1562static int do_server(struct sock_args *args, int ipc_fd)1563{1564	/* ipc_fd = -1 if no parent process to signal */1565	struct timeval timeout = { .tv_sec = prog_timeout }, *ptval = NULL;1566	unsigned char addr[sizeof(struct sockaddr_in6)] = {};1567	socklen_t alen = sizeof(addr);1568	int lsd, csd = -1;1569 1570	fd_set rfds;1571	int rc;1572 1573	if (args->serverns) {1574		if (switch_ns(args->serverns)) {1575			log_error("Could not set server netns to %s\n",1576				  args->serverns);1577			goto err_exit;1578		}1579		log_msg("Switched server netns\n");1580	}1581 1582	args->dev = args->server_dev;1583	args->expected_dev = args->expected_server_dev;1584	if (resolve_devices(args) || validate_addresses(args))1585		goto err_exit;1586 1587	if (prog_timeout)1588		ptval = &timeout;1589 1590	if (args->has_grp)1591		lsd = msock_server(args);1592	else1593		lsd = lsock_init(args);1594 1595	if (lsd < 0)1596		goto err_exit;1597 1598	if (args->bind_test_only) {1599		close(lsd);1600		ipc_write(ipc_fd, 1);1601		return 0;1602	}1603 1604	if (args->type != SOCK_STREAM) {1605		ipc_write(ipc_fd, 1);1606		rc = msg_loop(0, lsd, (void *) addr, alen, args);1607		close(lsd);1608		return rc;1609	}1610 1611	if (args->password && tcp_md5_remote(lsd, args)) {1612		close(lsd);1613		goto err_exit;1614	}1615 1616	ipc_write(ipc_fd, 1);1617	while (1) {1618		log_msg("waiting for client connection.\n");1619		FD_ZERO(&rfds);1620		FD_SET(lsd, &rfds);1621 1622		rc = select(lsd+1, &rfds, NULL, NULL, ptval);1623		if (rc == 0) {1624			rc = 2;1625			break;1626		}1627 1628		if (rc < 0) {1629			if (errno == EINTR)1630				continue;1631 1632			log_err_errno("select failed");1633			break;1634		}1635 1636		if (FD_ISSET(lsd, &rfds)) {1637 1638			csd = accept(lsd, (void *) addr, &alen);1639			if (csd < 0) {1640				log_err_errno("accept failed");1641				break;1642			}1643 1644			rc = show_sockstat(csd, args);1645			if (rc)1646				break;1647 1648			rc = check_device(csd, args);1649			if (rc)1650				break;1651		}1652 1653		rc = msg_loop(0, csd, (void *) addr, alen, args);1654		close(csd);1655 1656		if (!interactive)1657			break;1658	}1659 1660	close(lsd);1661 1662	return rc;1663err_exit:1664	ipc_write(ipc_fd, 0);1665	return 1;1666}1667 1668static int wait_for_connect(int sd)1669{1670	struct timeval _tv = { .tv_sec = prog_timeout }, *tv = NULL;1671	fd_set wfd;1672	int val = 0, sz = sizeof(val);1673	int rc;1674 1675	FD_ZERO(&wfd);1676	FD_SET(sd, &wfd);1677 1678	if (prog_timeout)1679		tv = &_tv;1680 1681	rc = select(FD_SETSIZE, NULL, &wfd, NULL, tv);1682	if (rc == 0) {1683		log_error("connect timed out\n");1684		return -2;1685	} else if (rc < 0) {1686		log_err_errno("select failed");1687		return -3;1688	}1689 1690	if (getsockopt(sd, SOL_SOCKET, SO_ERROR, &val, (socklen_t *)&sz) < 0) {1691		log_err_errno("getsockopt(SO_ERROR) failed");1692		return -4;1693	}1694 1695	if (val != 0) {1696		log_error("connect failed: %d: %s\n", val, strerror(val));1697		return -1;1698	}1699 1700	return 0;1701}1702 1703static int connectsock(void *addr, socklen_t alen, struct sock_args *args)1704{1705	int sd, rc = -1;1706	long flags;1707 1708	sd = socket(args->version, args->type, args->protocol);1709	if (sd < 0) {1710		log_err_errno("Failed to create socket");1711		return -1;1712	}1713 1714	flags = fcntl(sd, F_GETFL);1715	if ((flags < 0) || (fcntl(sd, F_SETFL, flags|O_NONBLOCK) < 0)) {1716		log_err_errno("Failed to set non-blocking option");1717		goto err;1718	}1719 1720	if (set_reuseport(sd) != 0)1721		goto err;1722 1723	if (set_dsfield(sd, args->version, args->dsfield) != 0)1724		goto err;1725 1726	if (args->client_dontroute && set_dontroute(sd) != 0)1727		goto err;1728 1729	if (args->dev && bind_to_device(sd, args->dev) != 0)1730		goto err;1731	else if (args->use_setsockopt &&1732		 set_unicast_if(sd, args->ifindex, args->version))1733		goto err;1734 1735	if (args->has_local_ip && bind_socket(sd, args))1736		goto err;1737 1738	if (args->type != SOCK_STREAM && !args->datagram_connect)1739		goto out;1740 1741	if (args->password && tcp_md5sig(sd, addr, alen, args))1742		goto err;1743 1744	if (args->bind_test_only)1745		goto out;1746 1747	if (connect(sd, addr, alen) < 0) {1748		if (errno != EINPROGRESS) {1749			log_err_errno("Failed to connect to remote host");1750			rc = -1;1751			goto err;1752		}1753		rc = wait_for_connect(sd);1754		if (rc < 0)1755			goto err;1756	}1757out:1758	return sd;1759 1760err:1761	close(sd);1762	return rc;1763}1764 1765static int do_client(struct sock_args *args)1766{1767	struct sockaddr_in sin = {1768		.sin_family = AF_INET,1769	};1770	struct sockaddr_in6 sin6 = {1771		.sin6_family = AF_INET6,1772	};1773	void *addr;1774	int alen;1775	int rc = 0;1776	int sd;1777 1778	if (!args->has_remote_ip && !args->has_grp) {1779		fprintf(stderr, "remote IP or multicast group not given\n");1780		return 1;1781	}1782 1783	if (args->clientns) {1784		if (switch_ns(args->clientns)) {1785			log_error("Could not set client netns to %s\n",1786				  args->clientns);1787			return 1;1788		}1789		log_msg("Switched client netns\n");1790	}1791 1792	args->local_addr_str = args->client_local_addr_str;1793	if (resolve_devices(args) || validate_addresses(args))1794		return 1;1795 1796	if ((args->use_setsockopt || args->use_cmsg) && !args->ifindex) {1797		fprintf(stderr, "Device binding not specified\n");1798		return 1;1799	}1800	if (args->use_setsockopt || args->use_cmsg)1801		args->dev = NULL;1802 1803	switch (args->version) {1804	case AF_INET:1805		sin.sin_port = htons(args->port);1806		if (args->has_grp)1807			sin.sin_addr = args->grp;1808		else1809			sin.sin_addr = args->remote_addr.in;1810		addr = &sin;1811		alen = sizeof(sin);1812		break;1813	case AF_INET6:1814		sin6.sin6_port = htons(args->port);1815		sin6.sin6_addr = args->remote_addr.in6;1816		sin6.sin6_scope_id = args->scope_id;1817		addr = &sin6;1818		alen = sizeof(sin6);1819		break;1820	}1821 1822	args->password = args->client_pw;1823 1824	if (args->has_grp)1825		sd = msock_client(args);1826	else1827		sd = connectsock(addr, alen, args);1828 1829	if (sd < 0)1830		return -sd;1831 1832	if (args->bind_test_only)1833		goto out;1834 1835	if (args->type == SOCK_STREAM) {1836		rc = show_sockstat(sd, args);1837		if (rc != 0)1838			goto out;1839	}1840 1841	rc = msg_loop(1, sd, addr, alen, args);1842 1843out:1844	close(sd);1845 1846	return rc;1847}1848 1849static char *random_msg(int len)1850{1851	int i, n = 0, olen = len + 1;1852	char *m;1853 1854	if (len <= 0)1855		return NULL;1856 1857	m = malloc(olen);1858	if (!m)1859		return NULL;1860 1861	while (len > 26) {1862		i = snprintf(m + n, olen - n, "%.26s",1863			     "abcdefghijklmnopqrstuvwxyz");1864		n += i;1865		len -= i;1866	}1867 1868	snprintf(m + n, olen - n, "%.*s", len,1869	     "abcdefghijklmnopqrstuvwxyz");1870	return m;1871}1872 1873static int ipc_child(int fd, struct sock_args *args)1874{1875	char *outbuf, *errbuf;1876	int rc = 1;1877 1878	outbuf = malloc(4096);1879	errbuf = malloc(4096);1880	if (!outbuf || !errbuf) {1881		fprintf(stderr, "server: Failed to allocate buffers for stdout and stderr\n");1882		goto out;1883	}1884 1885	setbuffer(stdout, outbuf, 4096);1886	setbuffer(stderr, errbuf, 4096);1887 1888	server_mode = 1; /* to tell log_msg in case we are in both_mode */1889 1890	/* when running in both mode, address validation applies1891	 * solely to client side1892	 */1893	args->has_expected_laddr = 0;1894	args->has_expected_raddr = 0;1895 1896	rc = do_server(args, fd);1897 1898out:1899	free(outbuf);1900	free(errbuf);1901 1902	return rc;1903}1904 1905static int ipc_parent(int cpid, int fd, struct sock_args *args)1906{1907	int client_status;1908	int status;1909	int buf;1910 1911	/* do the client-side function here in the parent process,1912	 * waiting to be told when to continue1913	 */1914	if (read(fd, &buf, sizeof(buf)) <= 0) {1915		log_err_errno("Failed to read IPC status from status");1916		return 1;1917	}1918	if (!buf) {1919		log_error("Server failed; can not continue\n");1920		return 1;1921	}1922	log_msg("Server is ready\n");1923 1924	client_status = do_client(args);1925	log_msg("parent is done!\n");1926 1927	if (kill(cpid, 0) == 0)1928		kill(cpid, SIGKILL);1929 1930	wait(&status);1931	return client_status;1932}1933 1934#define GETOPT_STR  "sr:l:c:Q:p:t:g:P:DRn:M:X:m:d:I:BN:O:SUCi6xL:0:1:2:3:Fbqf"1935#define OPT_FORCE_BIND_KEY_IFINDEX 10011936#define OPT_NO_BIND_KEY_IFINDEX 10021937#define OPT_CLIENT_DONTROUTE 10031938#define OPT_SERVER_DONTROUTE 10041939 1940static struct option long_opts[] = {1941	{"force-bind-key-ifindex", 0, 0, OPT_FORCE_BIND_KEY_IFINDEX},1942	{"no-bind-key-ifindex", 0, 0, OPT_NO_BIND_KEY_IFINDEX},1943	{"client-dontroute", 0, 0, OPT_CLIENT_DONTROUTE},1944	{"server-dontroute", 0, 0, OPT_SERVER_DONTROUTE},1945	{0, 0, 0, 0}1946};1947 1948static void print_usage(char *prog)1949{1950	printf(1951	"usage: %s OPTS\n"1952	"Required:\n"1953	"    -r addr       remote address to connect to (client mode only)\n"1954	"    -p port       port to connect to (client mode)/listen on (server mode)\n"1955	"                  (default: %d)\n"1956	"    -s            server mode (default: client mode)\n"1957	"    -t            timeout seconds (default: none)\n"1958	"\n"1959	"Optional:\n"1960	"    -B            do both client and server via fork and IPC\n"1961	"    -N ns         set client to network namespace ns (requires root)\n"1962	"    -O ns         set server to network namespace ns (requires root)\n"1963	"    -F            Restart server loop\n"1964	"    -6            IPv6 (default is IPv4)\n"1965	"    -P proto      protocol for socket: icmp, ospf (default: none)\n"1966	"    -D|R          datagram (D) / raw (R) socket (default stream)\n"1967	"    -l addr       local address to bind to in server mode\n"1968	"    -c addr       local address to bind to in client mode\n"1969	"    -Q dsfield    DS Field value of the socket (the IP_TOS or\n"1970	"                  IPV6_TCLASS socket option)\n"1971	"    -x            configure XFRM policy on socket\n"1972	"\n"1973	"    -d dev        bind socket to given device name\n"1974	"    -I dev        bind socket to given device name - server mode\n"1975	"    -S            use setsockopt (IP_UNICAST_IF or IP_MULTICAST_IF)\n"1976	"                  to set device binding\n"1977	"    -U            Use connect() and send() for datagram sockets\n"1978	"    -f            bind socket with the IP[V6]_FREEBIND option\n"1979	"    -C            use cmsg and IP_PKTINFO to specify device binding\n"1980	"\n"1981	"    -L len        send random message of given length\n"1982	"    -n num        number of times to send message\n"1983	"\n"1984	"    -M password   use MD5 sum protection\n"1985	"    -X password   MD5 password for client mode\n"1986	"    -m prefix/len prefix and length to use for MD5 key\n"1987	"    --no-bind-key-ifindex: Force TCP_MD5SIG_FLAG_IFINDEX off\n"1988	"    --force-bind-key-ifindex: Force TCP_MD5SIG_FLAG_IFINDEX on\n"1989	"        (default: only if -I is passed)\n"1990	"    --client-dontroute: don't use gateways for client socket: send\n"1991	"                        packets only if destination is on link (see\n"1992	"                        SO_DONTROUTE in socket(7))\n"1993	"    --server-dontroute: don't use gateways for server socket: send\n"1994	"                        packets only if destination is on link (see\n"1995	"                        SO_DONTROUTE in socket(7))\n"1996	"\n"1997	"    -g grp        multicast group (e.g., 239.1.1.1)\n"1998	"    -i            interactive mode (default is echo and terminate)\n"1999	"\n"2000	"    -0 addr       Expected local address\n"2001	"    -1 addr       Expected remote address\n"2002	"    -2 dev        Expected device name (or index) to receive packet\n"2003	"    -3 dev        Expected device name (or index) to receive packets - server mode\n"2004	"\n"2005	"    -b            Bind test only.\n"2006	"    -q            Be quiet. Run test without printing anything.\n"2007	, prog, DEFAULT_PORT);2008}2009 2010int main(int argc, char *argv[])2011{2012	struct sock_args args = {2013		.version = AF_INET,2014		.type    = SOCK_STREAM,2015		.port    = DEFAULT_PORT,2016	};2017	struct protoent *pe;2018	int both_mode = 0;2019	unsigned int tmp;2020	int forever = 0;2021	int fd[2];2022	int cpid;2023 2024	/* process inputs */2025	extern char *optarg;2026	int rc = 0;2027 2028	/*2029	 * process input args2030	 */2031 2032	while ((rc = getopt_long(argc, argv, GETOPT_STR, long_opts, NULL)) != -1) {2033		switch (rc) {2034		case 'B':2035			both_mode = 1;2036			break;2037		case 's':2038			server_mode = 1;2039			break;2040		case 'F':2041			forever = 1;2042			break;2043		case 'l':2044			args.has_local_ip = 1;2045			args.local_addr_str = optarg;2046			break;2047		case 'r':2048			args.has_remote_ip = 1;2049			args.remote_addr_str = optarg;2050			break;2051		case 'c':2052			args.has_local_ip = 1;2053			args.client_local_addr_str = optarg;2054			break;2055		case 'Q':2056			if (str_to_uint(optarg, 0, 255, &tmp) != 0) {2057				fprintf(stderr, "Invalid DS Field\n");2058				return 1;2059			}2060			args.dsfield = tmp;2061			break;2062		case 'p':2063			if (str_to_uint(optarg, 1, 65535, &tmp) != 0) {2064				fprintf(stderr, "Invalid port\n");2065				return 1;2066			}2067			args.port = (unsigned short) tmp;2068			break;2069		case 't':2070			if (str_to_uint(optarg, 0, INT_MAX,2071					&prog_timeout) != 0) {2072				fprintf(stderr, "Invalid timeout\n");2073				return 1;2074			}2075			break;2076		case 'D':2077			args.type = SOCK_DGRAM;2078			break;2079		case 'R':2080			args.type = SOCK_RAW;2081			args.port = 0;2082			if (!args.protocol)2083				args.protocol = IPPROTO_RAW;2084			break;2085		case 'P':2086			pe = getprotobyname(optarg);2087			if (pe) {2088				args.protocol = pe->p_proto;2089			} else {2090				if (str_to_uint(optarg, 0, 0xffff, &tmp) != 0) {2091					fprintf(stderr, "Invalid protocol\n");2092					return 1;2093				}2094				args.protocol = tmp;2095			}2096			break;2097		case 'n':2098			iter = atoi(optarg);2099			break;2100		case 'N':2101			args.clientns = optarg;2102			break;2103		case 'O':2104			args.serverns = optarg;2105			break;2106		case 'L':2107			msg = random_msg(atoi(optarg));2108			break;2109		case 'M':2110			args.password = optarg;2111			break;2112		case OPT_FORCE_BIND_KEY_IFINDEX:2113			args.bind_key_ifindex = 1;2114			break;2115		case OPT_NO_BIND_KEY_IFINDEX:2116			args.bind_key_ifindex = -1;2117			break;2118		case OPT_CLIENT_DONTROUTE:2119			args.client_dontroute = 1;2120			break;2121		case OPT_SERVER_DONTROUTE:2122			args.server_dontroute = 1;2123			break;2124		case 'X':2125			args.client_pw = optarg;2126			break;2127		case 'm':2128			args.md5_prefix_str = optarg;2129			break;2130		case 'S':2131			args.use_setsockopt = 1;2132			break;2133		case 'f':2134			args.use_freebind = 1;2135			break;2136		case 'C':2137			args.use_cmsg = 1;2138			break;2139		case 'd':2140			args.dev = optarg;2141			break;2142		case 'I':2143			args.server_dev = optarg;2144			break;2145		case 'i':2146			interactive = 1;2147			break;2148		case 'g':2149			args.has_grp = 1;2150			if (convert_addr(&args, optarg, ADDR_TYPE_MCAST) < 0)2151				return 1;2152			args.type = SOCK_DGRAM;2153			break;2154		case '6':2155			args.version = AF_INET6;2156			break;2157		case 'b':2158			args.bind_test_only = 1;2159			break;2160		case '0':2161			args.has_expected_laddr = 1;2162			args.expected_laddr_str = optarg;2163			break;2164		case '1':2165			args.has_expected_raddr = 1;2166			args.expected_raddr_str = optarg;2167			break;2168		case '2':2169			args.expected_dev = optarg;2170			break;2171		case '3':2172			args.expected_server_dev = optarg;2173			break;2174		case 'q':2175			quiet = 1;2176			break;2177		case 'x':2178			args.use_xfrm = 1;2179			break;2180		case 'U':2181			args.datagram_connect = 1;2182			break;2183		default:2184			print_usage(argv[0]);2185			return 1;2186		}2187	}2188 2189	if (args.password &&2190	    ((!args.has_remote_ip && !args.md5_prefix_str) ||2191	      args.type != SOCK_STREAM)) {2192		log_error("MD5 passwords apply to TCP only and require a remote ip for the password\n");2193		return 1;2194	}2195 2196	if (args.md5_prefix_str && !args.password) {2197		log_error("Prefix range for MD5 protection specified without a password\n");2198		return 1;2199	}2200 2201	if (iter == 0) {2202		fprintf(stderr, "Invalid number of messages to send\n");2203		return 1;2204	}2205 2206	if (args.type == SOCK_STREAM && !args.protocol)2207		args.protocol = IPPROTO_TCP;2208	if (args.type == SOCK_DGRAM && !args.protocol)2209		args.protocol = IPPROTO_UDP;2210 2211	if ((args.type == SOCK_STREAM || args.type == SOCK_DGRAM) &&2212	     args.port == 0) {2213		fprintf(stderr, "Invalid port number\n");2214		return 1;2215	}2216 2217	if ((both_mode || !server_mode) && !args.has_grp &&2218	    !args.has_remote_ip && !args.has_local_ip) {2219		fprintf(stderr,2220			"Local (server mode) or remote IP (client IP) required\n");2221		return 1;2222	}2223 2224	if (interactive) {2225		prog_timeout = 0;2226		msg = NULL;2227	}2228 2229	if (both_mode) {2230		if (pipe(fd) < 0) {2231			perror("pipe");2232			exit(1);2233		}2234 2235		cpid = fork();2236		if (cpid < 0) {2237			perror("fork");2238			exit(1);2239		}2240		if (cpid)2241			return ipc_parent(cpid, fd[0], &args);2242 2243		return ipc_child(fd[1], &args);2244	}2245 2246	if (server_mode) {2247		do {2248			rc = do_server(&args, -1);2249		} while (forever);2250 2251		return rc;2252	}2253	return do_client(&args);2254}2255