You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
142 lines
4.3 KiB
142 lines
4.3 KiB
commit 3a83f79024cc023a74c3892a1673542e8e972485 |
|
Author: Sergey Kolosov <skolosov@redhat.com> |
|
Date: Wed Apr 10 17:58:05 2024 +0200 |
|
|
|
socket: Add new test for connect |
|
|
|
This commit adds a simple bind/accept/connect test for an IPv4 TCP |
|
connection to a local process via the loopback interface. |
|
|
|
Reviewed-by: Arjun Shankar <arjun@redhat.com> |
|
|
|
diff -Nrup a/socket/Makefile b/socket/Makefile |
|
--- a/socket/Makefile 2024-05-19 21:52:59.775055152 -0400 |
|
+++ b/socket/Makefile 2024-05-19 22:05:27.717703460 -0400 |
|
@@ -33,8 +33,9 @@ routines := accept bind connect getpeern |
|
|
|
tests := \ |
|
tst-accept4 \ |
|
- tst-sockopt \ |
|
tst-cmsghdr \ |
|
+ tst-connect \ |
|
+ tst-sockopt \ |
|
# tests |
|
|
|
tests-internal := \ |
|
diff -Nrup a/socket/tst-connect.c b/socket/tst-connect.c |
|
--- a/socket/tst-connect.c 1969-12-31 19:00:00.000000000 -0500 |
|
+++ b/socket/tst-connect.c 2024-05-19 21:58:22.069058144 -0400 |
|
@@ -0,0 +1,113 @@ |
|
+/* Test the connect function. |
|
+ Copyright (C) 2024 Free Software Foundation, Inc. |
|
+ This file is part of the GNU C Library. |
|
+ |
|
+ The GNU C Library is free software; you can redistribute it and/or |
|
+ modify it under the terms of the GNU Lesser General Public |
|
+ License as published by the Free Software Foundation; either |
|
+ version 2.1 of the License, or (at your option) any later version. |
|
+ |
|
+ The GNU C Library is distributed in the hope that it will be useful, |
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
+ Lesser General Public License for more details. |
|
+ |
|
+ You should have received a copy of the GNU Lesser General Public |
|
+ License along with the GNU C Library; if not, see |
|
+ <https://www.gnu.org/licenses/>. */ |
|
+ |
|
+#include <arpa/inet.h> |
|
+#include <errno.h> |
|
+#include <fcntl.h> |
|
+#include <signal.h> |
|
+#include <stdbool.h> |
|
+#include <support/check.h> |
|
+#include <support/xsocket.h> |
|
+#include <support/xunistd.h> |
|
+#include <sys/socket.h> |
|
+#include <stdio.h> |
|
+ |
|
+static struct sockaddr_in server_address; |
|
+ |
|
+int |
|
+open_socket_inet_tcp (void) |
|
+{ |
|
+ int fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); |
|
+ if (fd < 0) |
|
+ { |
|
+ if (errno == EAFNOSUPPORT) |
|
+ FAIL_UNSUPPORTED ("The host does not support IPv4"); |
|
+ else |
|
+ FAIL_EXIT1 ("socket (AF_INET, SOCK_STREAM, IPPROTO_TCP): %m\n"); |
|
+ } |
|
+ return fd; |
|
+} |
|
+ |
|
+static pid_t |
|
+start_server (void) |
|
+{ |
|
+ server_address.sin_family = AF_INET; |
|
+ server_address.sin_port = 0; |
|
+ server_address.sin_addr.s_addr = htonl (INADDR_LOOPBACK); |
|
+ |
|
+ int server_sock = open_socket_inet_tcp (); |
|
+ |
|
+ xbind (server_sock, (struct sockaddr *) &server_address, |
|
+ sizeof (server_address)); |
|
+ |
|
+ socklen_t sa_len = sizeof (server_address); |
|
+ xgetsockname (server_sock, (struct sockaddr *) &server_address, &sa_len); |
|
+ xlisten (server_sock, 5); |
|
+ |
|
+ pid_t my_pid = xfork (); |
|
+ if (my_pid > 0) |
|
+ { |
|
+ xclose (server_sock); |
|
+ return my_pid; |
|
+ } |
|
+ |
|
+ struct sockaddr_in client_address; |
|
+ socklen_t ca_len = sizeof (server_address); |
|
+ int client_sock = xaccept (server_sock, (struct sockaddr *) &client_address, |
|
+ &ca_len); |
|
+ printf ("socket accepted %d\n", client_sock); |
|
+ |
|
+ _exit (0); |
|
+} |
|
+ |
|
+static int |
|
+do_test (void) |
|
+{ |
|
+ pid_t serv_pid; |
|
+ struct sockaddr_in peer; |
|
+ socklen_t peer_len; |
|
+ |
|
+ serv_pid = start_server (); |
|
+ int client_sock = open_socket_inet_tcp (); |
|
+ xconnect (client_sock, (const struct sockaddr *) &server_address, |
|
+ sizeof (server_address)); |
|
+ |
|
+ /* A second connect with same arguments should fail with EISCONN. */ |
|
+ int result = connect (client_sock, |
|
+ (const struct sockaddr *) &server_address, |
|
+ sizeof (server_address)); |
|
+ if (result == 0 || errno != EISCONN) |
|
+ FAIL_EXIT1 ("Second connect (%d), should fail with EISCONN: %m", |
|
+ client_sock); |
|
+ |
|
+ peer_len = sizeof (peer); |
|
+ xgetpeername (client_sock, (struct sockaddr *) &peer, &peer_len); |
|
+ TEST_COMPARE (peer_len, sizeof (peer)); |
|
+ TEST_COMPARE (peer.sin_port, server_address.sin_port); |
|
+ TEST_COMPARE_BLOB (&peer.sin_addr, sizeof (peer.sin_addr), |
|
+ &server_address.sin_addr, |
|
+ sizeof (server_address.sin_addr)); |
|
+ |
|
+ int status; |
|
+ xwaitpid (serv_pid, &status, 0); |
|
+ TEST_COMPARE (status, 0); |
|
+ |
|
+ return 0; |
|
+} |
|
+ |
|
+#include <support/test-driver.c>
|
|
|