1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci
3f08c3bdfSopenharmony_ci/*
4f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines  Corp., 2001
5f08c3bdfSopenharmony_ci */
6f08c3bdfSopenharmony_ci
7f08c3bdfSopenharmony_ci#include <stdio.h>
8f08c3bdfSopenharmony_ci#include <unistd.h>
9f08c3bdfSopenharmony_ci#include <errno.h>
10f08c3bdfSopenharmony_ci#include <fcntl.h>
11f08c3bdfSopenharmony_ci
12f08c3bdfSopenharmony_ci#include <sys/types.h>
13f08c3bdfSopenharmony_ci#include <sys/socket.h>
14f08c3bdfSopenharmony_ci#include <sys/un.h>
15f08c3bdfSopenharmony_ci
16f08c3bdfSopenharmony_ci#include <netinet/in.h>
17f08c3bdfSopenharmony_ci
18f08c3bdfSopenharmony_ci#include "tst_test.h"
19f08c3bdfSopenharmony_ci
20f08c3bdfSopenharmony_ciint inet_socket;
21f08c3bdfSopenharmony_ciint dev_null;
22f08c3bdfSopenharmony_ci
23f08c3bdfSopenharmony_cistruct sockaddr_in sin1, sin2, sin3;
24f08c3bdfSopenharmony_cistruct sockaddr_un sun;
25f08c3bdfSopenharmony_ci
26f08c3bdfSopenharmony_cistatic struct test_case {
27f08c3bdfSopenharmony_ci	int *socket_fd;
28f08c3bdfSopenharmony_ci	struct sockaddr *sockaddr;
29f08c3bdfSopenharmony_ci	socklen_t salen;
30f08c3bdfSopenharmony_ci	int retval;
31f08c3bdfSopenharmony_ci	int experrno;
32f08c3bdfSopenharmony_ci	char *desc;
33f08c3bdfSopenharmony_ci} tcases[] = {
34f08c3bdfSopenharmony_ci	{ &inet_socket, (struct sockaddr *)&sin1, 3, -1,
35f08c3bdfSopenharmony_ci	  EINVAL, "invalid salen" },
36f08c3bdfSopenharmony_ci	{ &dev_null, (struct sockaddr *)&sin1, sizeof(sin1), -1,
37f08c3bdfSopenharmony_ci	  ENOTSOCK, "invalid socket" },
38f08c3bdfSopenharmony_ci	{ &inet_socket, (struct sockaddr *)&sin2, sizeof(sin2), 0,
39f08c3bdfSopenharmony_ci	  0, "INADDR_ANYPORT"},
40f08c3bdfSopenharmony_ci	{ &inet_socket, (struct sockaddr *)&sun, sizeof(sun), -1,
41f08c3bdfSopenharmony_ci	  EAFNOSUPPORT, "UNIX-domain of current directory" },
42f08c3bdfSopenharmony_ci	{ &inet_socket, (struct sockaddr *)&sin3, sizeof(sin3), -1,
43f08c3bdfSopenharmony_ci	  EADDRNOTAVAIL, "non-local address" },
44f08c3bdfSopenharmony_ci};
45f08c3bdfSopenharmony_ci
46f08c3bdfSopenharmony_civoid verify_bind(unsigned int nr)
47f08c3bdfSopenharmony_ci{
48f08c3bdfSopenharmony_ci	struct test_case *tcase = &tcases[nr];
49f08c3bdfSopenharmony_ci
50f08c3bdfSopenharmony_ci	if (tcase->experrno) {
51f08c3bdfSopenharmony_ci		TST_EXP_FAIL(bind(*tcase->socket_fd, tcase->sockaddr, tcase->salen),
52f08c3bdfSopenharmony_ci		             tcase->experrno, "%s", tcase->desc);
53f08c3bdfSopenharmony_ci	} else {
54f08c3bdfSopenharmony_ci		TST_EXP_PASS(bind(*tcase->socket_fd, tcase->sockaddr, tcase->salen),
55f08c3bdfSopenharmony_ci		             "%s", tcase->desc);
56f08c3bdfSopenharmony_ci		SAFE_CLOSE(inet_socket);
57f08c3bdfSopenharmony_ci		inet_socket = SAFE_SOCKET(PF_INET, SOCK_STREAM, 0);
58f08c3bdfSopenharmony_ci	}
59f08c3bdfSopenharmony_ci}
60f08c3bdfSopenharmony_ci
61f08c3bdfSopenharmony_civoid test_setup(void)
62f08c3bdfSopenharmony_ci{
63f08c3bdfSopenharmony_ci	/* initialize sockaddr's */
64f08c3bdfSopenharmony_ci	sin1.sin_family = AF_INET;
65f08c3bdfSopenharmony_ci	/* this port must be unused! */
66f08c3bdfSopenharmony_ci	sin1.sin_port = TST_GET_UNUSED_PORT(AF_INET, SOCK_STREAM);
67f08c3bdfSopenharmony_ci	sin1.sin_addr.s_addr = INADDR_ANY;
68f08c3bdfSopenharmony_ci
69f08c3bdfSopenharmony_ci	sin2.sin_family = AF_INET;
70f08c3bdfSopenharmony_ci	sin2.sin_port = 0;
71f08c3bdfSopenharmony_ci	sin2.sin_addr.s_addr = INADDR_ANY;
72f08c3bdfSopenharmony_ci
73f08c3bdfSopenharmony_ci	sin3.sin_family = AF_INET;
74f08c3bdfSopenharmony_ci	sin3.sin_port = 0;
75f08c3bdfSopenharmony_ci	/* assumes 10.255.254.253 is not a local interface address! */
76f08c3bdfSopenharmony_ci	sin3.sin_addr.s_addr = htonl(0x0AFFFEFD);
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_ci	sun.sun_family = AF_UNIX;
79f08c3bdfSopenharmony_ci	strncpy(sun.sun_path, ".", sizeof(sun.sun_path));
80f08c3bdfSopenharmony_ci
81f08c3bdfSopenharmony_ci	inet_socket = SAFE_SOCKET(PF_INET, SOCK_STREAM, 0);
82f08c3bdfSopenharmony_ci	dev_null = SAFE_OPEN("/dev/null", O_WRONLY);
83f08c3bdfSopenharmony_ci}
84f08c3bdfSopenharmony_ci
85f08c3bdfSopenharmony_civoid test_cleanup(void)
86f08c3bdfSopenharmony_ci{
87f08c3bdfSopenharmony_ci	SAFE_CLOSE(inet_socket);
88f08c3bdfSopenharmony_ci	SAFE_CLOSE(dev_null);
89f08c3bdfSopenharmony_ci}
90f08c3bdfSopenharmony_ci
91f08c3bdfSopenharmony_cistatic struct tst_test test = {
92f08c3bdfSopenharmony_ci	.tcnt = ARRAY_SIZE(tcases),
93f08c3bdfSopenharmony_ci	.setup = test_setup,
94f08c3bdfSopenharmony_ci	.cleanup = test_cleanup,
95f08c3bdfSopenharmony_ci	.test = verify_bind,
96f08c3bdfSopenharmony_ci};
97