File Index
Files and directories
Sign in
FILE

tfo.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/net/tfo.c C
  1// SPDX-License-Identifier: GPL-2.0
  2#include <error.h>
  3#include <fcntl.h>
  4#include <limits.h>
  5#include <stdbool.h>
  6#include <stdint.h>
  7#include <stdio.h>
  8#include <stdlib.h>
  9#include <string.h>
 10#include <unistd.h>
 11#include <arpa/inet.h>
 12#include <sys/socket.h>
 13#include <netinet/tcp.h>
 14#include <errno.h>
 15
 16static int cfg_server;
 17static int cfg_client;
 18static int cfg_port = 8000;
 19static struct sockaddr_in6 cfg_addr;
 20static char *cfg_outfile;
 21
 22static int parse_address(const char *str, int port, struct sockaddr_in6 *sin6)
 23{
 24	int ret;
 25
 26	sin6->sin6_family = AF_INET6;
 27	sin6->sin6_port = htons(port);
 28
 29	ret = inet_pton(sin6->sin6_family, str, &sin6->sin6_addr);
 30	if (ret != 1) {
 31		/* fallback to plain IPv4 */
 32		ret = inet_pton(AF_INET, str, &sin6->sin6_addr.s6_addr32[3]);
 33		if (ret != 1)
 34			return -1;
 35
 36		/* add ::ffff prefix */
 37		sin6->sin6_addr.s6_addr32[0] = 0;
 38		sin6->sin6_addr.s6_addr32[1] = 0;
 39		sin6->sin6_addr.s6_addr16[4] = 0;
 40		sin6->sin6_addr.s6_addr16[5] = 0xffff;
 41	}
 42
 43	return 0;
 44}
 45
 46static void run_server(void)
 47{
 48	unsigned long qlen = 32;
 49	int fd, opt, connfd;
 50	socklen_t len;
 51	char buf[64];
 52	FILE *outfile;
 53
 54	outfile = fopen(cfg_outfile, "w");
 55	if (!outfile)
 56		error(1, errno, "fopen() outfile");
 57
 58	fd = socket(AF_INET6, SOCK_STREAM, 0);
 59	if (fd == -1)
 60		error(1, errno, "socket()");
 61
 62	opt = 1;
 63	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
 64		error(1, errno, "setsockopt(SO_REUSEADDR)");
 65
 66	if (setsockopt(fd, SOL_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen)) < 0)
 67		error(1, errno, "setsockopt(TCP_FASTOPEN)");
 68
 69	if (bind(fd, (struct sockaddr *)&cfg_addr, sizeof(cfg_addr)) < 0)
 70		error(1, errno, "bind()");
 71
 72	if (listen(fd, 5) < 0)
 73		error(1, errno, "listen()");
 74
 75	len = sizeof(cfg_addr);
 76	connfd = accept(fd, (struct sockaddr *)&cfg_addr, &len);
 77	if (connfd < 0)
 78		error(1, errno, "accept()");
 79
 80	len = sizeof(opt);
 81	if (getsockopt(connfd, SOL_SOCKET, SO_INCOMING_NAPI_ID, &opt, &len) < 0)
 82		error(1, errno, "getsockopt(SO_INCOMING_NAPI_ID)");
 83
 84	if (read(connfd, buf, 64) < 0)
 85		perror("read()");
 86	fprintf(outfile, "%d\n", opt);
 87
 88	fclose(outfile);
 89	close(connfd);
 90	close(fd);
 91}
 92
 93static void run_client(void)
 94{
 95	int fd;
 96	char *msg = "Hello, world!";
 97
 98	fd = socket(AF_INET6, SOCK_STREAM, 0);
 99	if (fd == -1)
100		error(1, errno, "socket()");
101
102	sendto(fd, msg, strlen(msg), MSG_FASTOPEN, (struct sockaddr *)&cfg_addr, sizeof(cfg_addr));
103
104	close(fd);
105}
106
107static void usage(const char *filepath)
108{
109	error(1, 0, "Usage: %s (-s|-c) -h<server_ip> -p<port> -o<outfile> ", filepath);
110}
111
112static void parse_opts(int argc, char **argv)
113{
114	struct sockaddr_in6 *addr6 = (void *) &cfg_addr;
115	char *addr = NULL;
116	int ret;
117	int c;
118
119	if (argc <= 1)
120		usage(argv[0]);
121
122	while ((c = getopt(argc, argv, "sch:p:o:")) != -1) {
123		switch (c) {
124		case 's':
125			if (cfg_client)
126				error(1, 0, "Pass one of -s or -c");
127			cfg_server = 1;
128			break;
129		case 'c':
130			if (cfg_server)
131				error(1, 0, "Pass one of -s or -c");
132			cfg_client = 1;
133			break;
134		case 'h':
135			addr = optarg;
136			break;
137		case 'p':
138			cfg_port = strtoul(optarg, NULL, 0);
139			break;
140		case 'o':
141			cfg_outfile = strdup(optarg);
142			if (!cfg_outfile)
143				error(1, 0, "outfile invalid");
144			break;
145		}
146	}
147
148	if (cfg_server && addr)
149		error(1, 0, "Server cannot have -h specified");
150
151	memset(addr6, 0, sizeof(*addr6));
152	addr6->sin6_family = AF_INET6;
153	addr6->sin6_port = htons(cfg_port);
154	addr6->sin6_addr = in6addr_any;
155	if (addr) {
156		ret = parse_address(addr, cfg_port, addr6);
157		if (ret)
158			error(1, 0, "Client address parse error: %s", addr);
159	}
160}
161
162int main(int argc, char **argv)
163{
164	parse_opts(argc, argv);
165
166	if (cfg_server)
167		run_server();
168	else if (cfg_client)
169		run_client();
170
171	return 0;
172}
~/ Read-only file preview.