blob: 64e48bcb4a4628047cf088fb43016e2d63d4cc4e [file] [log] [blame]
Harald Welte4ffb43f2017-01-27 10:29:49 +01001/*
2 * (C) 2017 by Harald Welte <laforge@gnumonks.org>
3 * All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 */
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <unistd.h>
24#include <string.h>
25#include <fcntl.h>
Pau Espin Pedrolcd133312020-08-19 17:25:04 +020026#include <inttypes.h>
Pau Espin Pedrold9e04172020-08-31 18:56:10 +020027#include <errno.h>
Harald Welte4ffb43f2017-01-27 10:29:49 +010028
29#include <sys/socket.h>
30#include <arpa/inet.h>
31#include <netinet/in.h>
32
Philipp Maier6f0f5602017-02-09 14:09:06 +010033#include <osmocom/core/application.h>
Harald Welte4ffb43f2017-01-27 10:29:49 +010034#include <osmocom/core/utils.h>
35#include <osmocom/core/socket.h>
Philipp Maier6f0f5602017-02-09 14:09:06 +010036#include <osmocom/core/logging.h>
Pau Espin Pedrolcd133312020-08-19 17:25:04 +020037#include <osmocom/core/bits.h>
Harald Welte4ffb43f2017-01-27 10:29:49 +010038
39#include "../config.h"
40
Neels Hofmeyra829b452018-04-05 03:02:35 +020041void *ctx = NULL;
42
Harald Welte4ffb43f2017-01-27 10:29:49 +010043static int test_sockinit(void)
44{
45 int fd, rc;
46 char *name;
47
48 printf("Checking osmo_sock_init() with bind to a random local UDP port\n");
49 fd = osmo_sock_init(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
50 "0.0.0.0", 0, OSMO_SOCK_F_BIND);
51 OSMO_ASSERT(fd >= 0);
Neels Hofmeyra829b452018-04-05 03:02:35 +020052 name = osmo_sock_get_name(ctx, fd);
Harald Welte4ffb43f2017-01-27 10:29:49 +010053 /* expect it to be not connected. We cannot match on INADDR_ANY,
54 * as apparently that won't work on FreeBSD if there's only one
55 * address (e.g. 127.0.0.1) assigned to the entire system, like
56 * the Osmocom FreeBSD build slaves */
Neels Hofmeyr1f82d0a2017-06-21 22:54:46 +020057 OSMO_ASSERT(!strncmp(name, "(r=NULL<->", 9));
Harald Welte4ffb43f2017-01-27 10:29:49 +010058 talloc_free(name);
59 /* expect it to be blocking */
60 rc = fcntl(fd, F_GETFL);
61 OSMO_ASSERT(!(rc & O_NONBLOCK));
62 close(fd);
63
64 printf("Checking for OSMO_SOCK_F_NONBLOCK\n");
65 fd = osmo_sock_init(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
66 "0.0.0.0", 0, OSMO_SOCK_F_BIND|OSMO_SOCK_F_NONBLOCK);
67 OSMO_ASSERT(fd >= 0);
68 /* expect it to be blocking */
69 rc = fcntl(fd, F_GETFL);
70 OSMO_ASSERT(rc & O_NONBLOCK);
71 close(fd);
72
73 printf("Checking for invalid flags\n");
74 fd = osmo_sock_init(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
75 "0.0.0.0", 0, OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT);
76 OSMO_ASSERT(fd < 0);
77
78 return 0;
79}
80
Harald Weltedda70fc2017-04-08 20:52:33 +020081static int test_sockinit2(void)
82{
83 int fd, rc;
84 char *name;
85
86 printf("Checking osmo_sock_init2() with bind to a random local UDP port\n");
87 fd = osmo_sock_init2(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
88 "0.0.0.0", 0, NULL, 0, OSMO_SOCK_F_BIND);
89 OSMO_ASSERT(fd >= 0);
Neels Hofmeyra829b452018-04-05 03:02:35 +020090 name = osmo_sock_get_name(ctx, fd);
Harald Weltedda70fc2017-04-08 20:52:33 +020091 /* expect it to be not connected. We cannot match on INADDR_ANY,
92 * as apparently that won't work on FreeBSD if there's only one
93 * address (e.g. 127.0.0.1) assigned to the entire system, like
94 * the Osmocom FreeBSD build slaves */
Neels Hofmeyr1f82d0a2017-06-21 22:54:46 +020095 OSMO_ASSERT(!strncmp(name, "(r=NULL<->", 9));
Harald Weltedda70fc2017-04-08 20:52:33 +020096 talloc_free(name);
97 /* expect it to be blocking */
98 rc = fcntl(fd, F_GETFL);
99 OSMO_ASSERT(!(rc & O_NONBLOCK));
100 close(fd);
101
102 printf("Checking osmo_sock_init2() for OSMO_SOCK_F_NONBLOCK\n");
103 fd = osmo_sock_init2(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
104 "0.0.0.0", 0, NULL, 0, OSMO_SOCK_F_BIND|OSMO_SOCK_F_NONBLOCK);
105 OSMO_ASSERT(fd >= 0);
106 /* expect it to be blocking */
107 rc = fcntl(fd, F_GETFL);
108 OSMO_ASSERT(rc & O_NONBLOCK);
109 close(fd);
110
111 printf("Checking osmo_sock_init2() for invalid flags\n");
112 fd = osmo_sock_init2(AF_INET, SOCK_DGRAM, IPPROTO_UDP, "0.0.0.0", 0, NULL, 0, 0);
113 OSMO_ASSERT(fd < 0);
114
115 printf("Checking osmo_sock_init2() for combined BIND + CONNECT\n");
116 fd = osmo_sock_init2(AF_INET, SOCK_DGRAM, IPPROTO_UDP, "127.0.0.1", 0, "127.0.0.1", 53,
117 OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT);
118 OSMO_ASSERT(fd >= 0);
Neels Hofmeyra829b452018-04-05 03:02:35 +0200119 name = osmo_sock_get_name(ctx, fd);
Harald Weltedda70fc2017-04-08 20:52:33 +0200120#ifndef __FreeBSD__
121 /* For some reason, on the jenkins.osmocom.org build slave with
122 * FreeBSD 10 inside a jail, it fails. Works fine on laforge's
123 * FreeBSD 10 or 11 VM at home */
Neels Hofmeyr1f82d0a2017-06-21 22:54:46 +0200124 OSMO_ASSERT(!strncmp(name, "(r=127.0.0.1:53<->l=127.0.0.1", 29));
Harald Weltedda70fc2017-04-08 20:52:33 +0200125#endif
Alexander Couzens2c962f52020-06-03 00:28:02 +0200126
127 printf("Checking osmo_sock_init2(AF_UNSPEC) must fail on mixed IPv4 & IPv6\n");
128 fd = osmo_sock_init2(AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "127.0.0.1", 0, "::1", 53,
129 OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT);
130 OSMO_ASSERT(fd < 0);
131
132 printf("Checking osmo_sock_init2(AF_UNSPEC) must fail on mixed IPv6 & IPv4\n");
133 fd = osmo_sock_init2(AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "::1", 0, "127.0.0.1", 53,
134 OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT);
135 OSMO_ASSERT(fd < 0);
136
137 printf("Checking osmo_sock_init2(AF_UNSPEC) BIND + CONNECT on IPv4\n");
138 fd = osmo_sock_init2(AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "127.0.0.1", 0, "127.0.0.1", 53,
139 OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT);
140 OSMO_ASSERT(fd >= 0);
141
142 printf("Checking osmo_sock_init2(AF_UNSPEC) BIND + CONNECT on IPv6\n");
143 fd = osmo_sock_init2(AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "::1", 0, "::1", 53,
144 OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT);
145 OSMO_ASSERT(fd >= 0);
146
Pau Espin Pedrold9e04172020-08-31 18:56:10 +0200147 printf("Checking osmo_sock_init2(AF_UNSPEC) BIND on IPv4\n");
148 fd = osmo_sock_init2(AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "127.0.0.1", 0, NULL, 0,
149 OSMO_SOCK_F_BIND);
Pau Espin Pedrold8cf52b2020-08-31 19:00:59 +0200150 OSMO_ASSERT(fd >= 0);
Pau Espin Pedrold9e04172020-08-31 18:56:10 +0200151
Harald Weltedda70fc2017-04-08 20:52:33 +0200152 talloc_free(name);
153
154 return 0;
155}
156
Alexander Couzensea198392020-08-01 22:02:03 +0200157static int test_get_ip_and_port()
158{
159 int fd, rc;
160 char ip[INET6_ADDRSTRLEN] = { };
161 char port[6] = { };
162
163 printf("Checking test_get_ip_and_port() for combined BIND + CONNECT on IPv4\n");
164 fd = osmo_sock_init2(AF_INET, SOCK_DGRAM, IPPROTO_UDP, "127.0.0.1", 0, "127.0.0.1", 55,
165 OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT);
166
167 OSMO_ASSERT(fd >= 0);
168
169 /* get the remote */
170 rc = osmo_sock_get_ip_and_port(fd, ip, sizeof(ip), port, sizeof(port), false);
171 OSMO_ASSERT(rc == 0);
172 OSMO_ASSERT(strncmp(ip, "127.0.0.1", INET6_ADDRSTRLEN) == 0);
173 OSMO_ASSERT(strncmp(port, "55", 6) == 0);
174
175 printf("Checking test_get_ip_and_port() for combined BIND + CONNECT on IPv6\n");
176 fd = osmo_sock_init2(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, "::1", 0, "::1", 55,
177 OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT);
178 OSMO_ASSERT(fd >= 0);
179
180 /* get the remote */
181 rc = osmo_sock_get_ip_and_port(fd, ip, sizeof(ip), port, sizeof(port), false);
182 OSMO_ASSERT(rc == 0);
183 OSMO_ASSERT(strncmp(ip, "::1", INET6_ADDRSTRLEN) == 0);
184 OSMO_ASSERT(strncmp(port, "55", 6) == 0);
185
186 return 0;
187}
188
Philipp Maier6f0f5602017-02-09 14:09:06 +0100189const struct log_info_cat default_categories[] = {
190};
191
192static struct log_info info = {
193 .cat = default_categories,
194 .num_cat = ARRAY_SIZE(default_categories),
195};
196
Harald Welte4ffb43f2017-01-27 10:29:49 +0100197int main(int argc, char *argv[])
198{
Neels Hofmeyra829b452018-04-05 03:02:35 +0200199 ctx = talloc_named_const(NULL, 0, "socket_test");
200 osmo_init_logging2(ctx, &info);
Philipp Maier6f0f5602017-02-09 14:09:06 +0100201 log_set_use_color(osmo_stderr_target, 0);
202 log_set_print_filename(osmo_stderr_target, 0);
203
Harald Welte4ffb43f2017-01-27 10:29:49 +0100204 test_sockinit();
Harald Weltedda70fc2017-04-08 20:52:33 +0200205 test_sockinit2();
Alexander Couzensea198392020-08-01 22:02:03 +0200206 test_get_ip_and_port();
Philipp Maier6f0f5602017-02-09 14:09:06 +0100207
208 return EXIT_SUCCESS;
Harald Welte4ffb43f2017-01-27 10:29:49 +0100209}