tools/testing/selftests/net/so_rcv_listener.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/net/so_rcv_listener.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/net/so_rcv_listener.c
Extension
.c
Size
3614 bytes
Lines
169
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct options {
	__u32 val;
	int name;
	int rcvname;
	const char *host;
	const char *service;
} opt;

static void __attribute__((noreturn)) usage(const char *bin)
{
	printf("Usage: %s [opts] <dst host> <dst port / service>\n", bin);
	printf("Options:\n"
		"\t\t-M val  Test SO_RCVMARK\n"
		"\t\t-P val  Test SO_RCVPRIORITY\n"
		"");
	exit(EXIT_FAILURE);
}

static void parse_args(int argc, char *argv[])
{
	int o;

	while ((o = getopt(argc, argv, "M:P:")) != -1) {
		switch (o) {
		case 'M':
			opt.val = atoi(optarg);
			opt.name = SO_MARK;
			opt.rcvname = SO_RCVMARK;
			break;
		case 'P':
			opt.val = atoi(optarg);
			opt.name = SO_PRIORITY;
			opt.rcvname = SO_RCVPRIORITY;
			break;
		default:
			usage(argv[0]);
			break;
		}
	}

	if (optind != argc - 2)
		usage(argv[0]);

	opt.host = argv[optind];
	opt.service = argv[optind + 1];
}

int main(int argc, char *argv[])
{
	int err = 0;
	int recv_fd = -1;
	int ret_value = 0;
	__u32 recv_val;
	struct cmsghdr *cmsg;
	char cbuf[CMSG_SPACE(sizeof(__u32))];
	char recv_buf[CMSG_SPACE(sizeof(__u32))];
	struct iovec iov[1];
	struct msghdr msg;
	struct sockaddr_in recv_addr4;
	struct sockaddr_in6 recv_addr6;

	parse_args(argc, argv);

	int family = strchr(opt.host, ':') ? AF_INET6 : AF_INET;

	recv_fd = socket(family, SOCK_DGRAM, IPPROTO_UDP);
	if (recv_fd < 0) {
		perror("Can't open recv socket");
		ret_value = -errno;
		goto cleanup;
	}

	err = setsockopt(recv_fd, SOL_SOCKET, opt.rcvname, &opt.val, sizeof(opt.val));
	if (err < 0) {
		perror("Recv setsockopt error");
		ret_value = -errno;
		goto cleanup;
	}

	if (family == AF_INET) {
		memset(&recv_addr4, 0, sizeof(recv_addr4));
		recv_addr4.sin_family = family;
		recv_addr4.sin_port = htons(atoi(opt.service));

		if (inet_pton(family, opt.host, &recv_addr4.sin_addr) <= 0) {
			perror("Invalid IPV4 address");
			ret_value = -errno;
			goto cleanup;
		}

Annotation

Implementation Notes