Skip to content

Commit 749c87e

Browse files
authored
Change port from uint16_t to uint32_t, to support VSOCK (#613)
1 parent df64f57 commit 749c87e

File tree

9 files changed

+226
-74
lines changed

9 files changed

+226
-74
lines changed

include/aws/io/channel_bootstrap.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ struct aws_server_bootstrap {
178178
struct aws_socket_channel_bootstrap_options {
179179
struct aws_client_bootstrap *bootstrap;
180180
const char *host_name;
181-
uint16_t port;
181+
uint32_t port;
182182
const struct aws_socket_options *socket_options;
183183
const struct aws_tls_connection_options *tls_options;
184184
aws_client_bootstrap_on_channel_event_fn *creation_callback;
@@ -208,7 +208,7 @@ struct aws_socket_channel_bootstrap_options {
208208
struct aws_server_socket_channel_bootstrap_options {
209209
struct aws_server_bootstrap *bootstrap;
210210
const char *host_name;
211-
uint16_t port;
211+
uint32_t port;
212212
const struct aws_socket_options *socket_options;
213213
const struct aws_tls_connection_options *tls_options;
214214
aws_server_bootstrap_on_accept_channel_setup_fn *incoming_callback;

include/aws/io/socket.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ typedef void(aws_socket_on_readable_fn)(struct aws_socket *socket, int error_cod
9898
#endif
9999
struct aws_socket_endpoint {
100100
char address[AWS_ADDRESS_MAX_LEN];
101-
uint16_t port;
101+
uint32_t port;
102102
};
103103

104104
struct aws_socket {
@@ -302,6 +302,22 @@ AWS_IO_API int aws_socket_get_error(struct aws_socket *socket);
302302
*/
303303
AWS_IO_API bool aws_socket_is_open(struct aws_socket *socket);
304304

305+
/**
306+
* Raises AWS_IO_SOCKET_INVALID_ADDRESS and logs an error if connecting to this port is illegal.
307+
* For example, port must be in range 1-65535 to connect with IPv4.
308+
* These port values would fail eventually in aws_socket_connect(),
309+
* but you can use this function to validate earlier.
310+
*/
311+
AWS_IO_API int aws_socket_validate_port_for_connect(uint32_t port, enum aws_socket_domain domain);
312+
313+
/**
314+
* Raises AWS_IO_SOCKET_INVALID_ADDRESS and logs an error if binding to this port is illegal.
315+
* For example, port must in range 0-65535 to bind with IPv4.
316+
* These port values would fail eventually in aws_socket_bind(),
317+
* but you can use this function to validate earlier.
318+
*/
319+
AWS_IO_API int aws_socket_validate_port_for_bind(uint32_t port, enum aws_socket_domain domain);
320+
305321
/**
306322
* Assigns a random address (UUID) for use with AWS_SOCKET_LOCAL (Unix Domain Sockets).
307323
* For use in internal tests only.

source/channel_bootstrap.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ struct client_connection_args {
118118
aws_client_bootstrap_on_channel_event_fn *shutdown_callback;
119119
struct client_channel_data channel_data;
120120
struct aws_socket_options outgoing_options;
121-
uint16_t outgoing_port;
121+
uint32_t outgoing_port;
122122
struct aws_string *host_name;
123123
void *user_data;
124124
uint8_t addresses_count;
@@ -764,14 +764,14 @@ int aws_client_bootstrap_new_socket_channel(struct aws_socket_channel_bootstrap_
764764
}
765765

766766
const char *host_name = options->host_name;
767-
uint16_t port = options->port;
767+
uint32_t port = options->port;
768768

769769
AWS_LOGF_TRACE(
770770
AWS_LS_IO_CHANNEL_BOOTSTRAP,
771-
"id=%p: attempting to initialize a new client channel to %s:%d",
771+
"id=%p: attempting to initialize a new client channel to %s:%u",
772772
(void *)bootstrap,
773773
host_name,
774-
(int)port);
774+
port);
775775

776776
aws_ref_count_init(
777777
&client_connection_args->ref_count,
@@ -1363,10 +1363,10 @@ struct aws_socket *aws_server_bootstrap_new_socket_listener(
13631363
AWS_LOGF_INFO(
13641364
AWS_LS_IO_CHANNEL_BOOTSTRAP,
13651365
"id=%p: attempting to initialize a new "
1366-
"server socket listener for %s:%d",
1366+
"server socket listener for %s:%u",
13671367
(void *)bootstrap_options->bootstrap,
13681368
bootstrap_options->host_name,
1369-
(int)bootstrap_options->port);
1369+
bootstrap_options->port);
13701370

13711371
aws_ref_count_init(
13721372
&server_connection_args->ref_count,

source/posix/socket.c

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -340,18 +340,7 @@ static int s_update_local_endpoint(struct aws_socket *socket) {
340340
} else if (address.ss_family == AF_VSOCK) {
341341
struct sockaddr_vm *s = (struct sockaddr_vm *)&address;
342342

343-
/* VSOCK port is 32bit, but aws_socket_endpoint.port is only 16bit.
344-
* Hopefully this isn't an issue, since users can only pass in 16bit values.
345-
* But if it becomes an issue, we'll need to make aws_socket_endpoint more flexible */
346-
if (s->svm_port > UINT16_MAX) {
347-
AWS_LOGF_ERROR(
348-
AWS_LS_IO_SOCKET,
349-
"id=%p fd=%d: aws_socket_endpoint can't deal with VSOCK port > UINT16_MAX",
350-
(void *)socket,
351-
socket->io_handle.data.fd);
352-
return aws_raise_error(AWS_IO_SOCKET_INVALID_ADDRESS);
353-
}
354-
tmp_endpoint.port = (uint16_t)s->svm_port;
343+
tmp_endpoint.port = s->svm_port;
355344

356345
snprintf(tmp_endpoint.address, sizeof(tmp_endpoint.address), "%" PRIu32, s->svm_cid);
357346
return AWS_OP_SUCCESS;
@@ -642,18 +631,22 @@ int aws_socket_connect(
642631
return AWS_OP_ERR;
643632
}
644633

634+
if (aws_socket_validate_port_for_connect(remote_endpoint->port, socket->options.domain)) {
635+
return AWS_OP_ERR;
636+
}
637+
645638
struct socket_address address;
646639
AWS_ZERO_STRUCT(address);
647640
socklen_t sock_size = 0;
648641
int pton_err = 1;
649642
if (socket->options.domain == AWS_SOCKET_IPV4) {
650643
pton_err = inet_pton(AF_INET, remote_endpoint->address, &address.sock_addr_types.addr_in.sin_addr);
651-
address.sock_addr_types.addr_in.sin_port = htons(remote_endpoint->port);
644+
address.sock_addr_types.addr_in.sin_port = htons((uint16_t)remote_endpoint->port);
652645
address.sock_addr_types.addr_in.sin_family = AF_INET;
653646
sock_size = sizeof(address.sock_addr_types.addr_in);
654647
} else if (socket->options.domain == AWS_SOCKET_IPV6) {
655648
pton_err = inet_pton(AF_INET6, remote_endpoint->address, &address.sock_addr_types.addr_in6.sin6_addr);
656-
address.sock_addr_types.addr_in6.sin6_port = htons(remote_endpoint->port);
649+
address.sock_addr_types.addr_in6.sin6_port = htons((uint16_t)remote_endpoint->port);
657650
address.sock_addr_types.addr_in6.sin6_family = AF_INET6;
658651
sock_size = sizeof(address.sock_addr_types.addr_in6);
659652
} else if (socket->options.domain == AWS_SOCKET_LOCAL) {
@@ -664,7 +657,7 @@ int aws_socket_connect(
664657
} else if (socket->options.domain == AWS_SOCKET_VSOCK) {
665658
pton_err = parse_cid(remote_endpoint->address, &address.sock_addr_types.vm_addr.svm_cid);
666659
address.sock_addr_types.vm_addr.svm_family = AF_VSOCK;
667-
address.sock_addr_types.vm_addr.svm_port = (unsigned int)remote_endpoint->port;
660+
address.sock_addr_types.vm_addr.svm_port = remote_endpoint->port;
668661
sock_size = sizeof(address.sock_addr_types.vm_addr);
669662
#endif
670663
} else {
@@ -676,21 +669,21 @@ int aws_socket_connect(
676669
int errno_value = errno; /* Always cache errno before potential side-effect */
677670
AWS_LOGF_DEBUG(
678671
AWS_LS_IO_SOCKET,
679-
"id=%p fd=%d: failed to parse address %s:%d.",
672+
"id=%p fd=%d: failed to parse address %s:%u.",
680673
(void *)socket,
681674
socket->io_handle.data.fd,
682675
remote_endpoint->address,
683-
(int)remote_endpoint->port);
676+
remote_endpoint->port);
684677
return aws_raise_error(s_convert_pton_error(pton_err, errno_value));
685678
}
686679

687680
AWS_LOGF_DEBUG(
688681
AWS_LS_IO_SOCKET,
689-
"id=%p fd=%d: connecting to endpoint %s:%d.",
682+
"id=%p fd=%d: connecting to endpoint %s:%u.",
690683
(void *)socket,
691684
socket->io_handle.data.fd,
692685
remote_endpoint->address,
693-
(int)remote_endpoint->port);
686+
remote_endpoint->port);
694687

695688
socket->state = CONNECTING;
696689
socket->remote_endpoint = *remote_endpoint;
@@ -806,26 +799,30 @@ int aws_socket_bind(struct aws_socket *socket, const struct aws_socket_endpoint
806799
return AWS_OP_ERR;
807800
}
808801

802+
if (aws_socket_validate_port_for_bind(local_endpoint->port, socket->options.domain)) {
803+
return AWS_OP_ERR;
804+
}
805+
809806
AWS_LOGF_INFO(
810807
AWS_LS_IO_SOCKET,
811-
"id=%p fd=%d: binding to %s:%d.",
808+
"id=%p fd=%d: binding to %s:%u.",
812809
(void *)socket,
813810
socket->io_handle.data.fd,
814811
local_endpoint->address,
815-
(int)local_endpoint->port);
812+
local_endpoint->port);
816813

817814
struct socket_address address;
818815
AWS_ZERO_STRUCT(address);
819816
socklen_t sock_size = 0;
820817
int pton_err = 1;
821818
if (socket->options.domain == AWS_SOCKET_IPV4) {
822819
pton_err = inet_pton(AF_INET, local_endpoint->address, &address.sock_addr_types.addr_in.sin_addr);
823-
address.sock_addr_types.addr_in.sin_port = htons(local_endpoint->port);
820+
address.sock_addr_types.addr_in.sin_port = htons((uint16_t)local_endpoint->port);
824821
address.sock_addr_types.addr_in.sin_family = AF_INET;
825822
sock_size = sizeof(address.sock_addr_types.addr_in);
826823
} else if (socket->options.domain == AWS_SOCKET_IPV6) {
827824
pton_err = inet_pton(AF_INET6, local_endpoint->address, &address.sock_addr_types.addr_in6.sin6_addr);
828-
address.sock_addr_types.addr_in6.sin6_port = htons(local_endpoint->port);
825+
address.sock_addr_types.addr_in6.sin6_port = htons((uint16_t)local_endpoint->port);
829826
address.sock_addr_types.addr_in6.sin6_family = AF_INET6;
830827
sock_size = sizeof(address.sock_addr_types.addr_in6);
831828
} else if (socket->options.domain == AWS_SOCKET_LOCAL) {
@@ -836,7 +833,7 @@ int aws_socket_bind(struct aws_socket *socket, const struct aws_socket_endpoint
836833
} else if (socket->options.domain == AWS_SOCKET_VSOCK) {
837834
pton_err = parse_cid(local_endpoint->address, &address.sock_addr_types.vm_addr.svm_cid);
838835
address.sock_addr_types.vm_addr.svm_family = AF_VSOCK;
839-
address.sock_addr_types.vm_addr.svm_port = (unsigned int)local_endpoint->port;
836+
address.sock_addr_types.vm_addr.svm_port = local_endpoint->port;
840837
sock_size = sizeof(address.sock_addr_types.vm_addr);
841838
#endif
842839
} else {
@@ -848,11 +845,11 @@ int aws_socket_bind(struct aws_socket *socket, const struct aws_socket_endpoint
848845
int errno_value = errno; /* Always cache errno before potential side-effect */
849846
AWS_LOGF_ERROR(
850847
AWS_LS_IO_SOCKET,
851-
"id=%p fd=%d: failed to parse address %s:%d.",
848+
"id=%p fd=%d: failed to parse address %s:%u.",
852849
(void *)socket,
853850
socket->io_handle.data.fd,
854851
local_endpoint->address,
855-
(int)local_endpoint->port);
852+
local_endpoint->port);
856853
return aws_raise_error(s_convert_pton_error(pton_err, errno_value));
857854
}
858855

@@ -882,7 +879,7 @@ int aws_socket_bind(struct aws_socket *socket, const struct aws_socket_endpoint
882879

883880
AWS_LOGF_DEBUG(
884881
AWS_LS_IO_SOCKET,
885-
"id=%p fd=%d: successfully bound to %s:%d",
882+
"id=%p fd=%d: successfully bound to %s:%u",
886883
(void *)socket,
887884
socket->io_handle.data.fd,
888885
socket->local_endpoint.address,
@@ -996,7 +993,7 @@ static void s_socket_accept_event(
996993

997994
new_sock->local_endpoint = socket->local_endpoint;
998995
new_sock->state = CONNECTED_READ | CONNECTED_WRITE;
999-
uint16_t port = 0;
996+
uint32_t port = 0;
1000997

1001998
/* get the info on the incoming socket's address */
1002999
if (in_addr.ss_family == AF_INET) {

source/socket_shared.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0.
4+
*/
5+
#include <aws/io/socket.h>
6+
7+
#include <aws/io/logging.h>
8+
9+
/* common validation for connect() and bind() */
10+
static int s_socket_validate_port_for_domain(uint32_t port, enum aws_socket_domain domain) {
11+
switch (domain) {
12+
case AWS_SOCKET_IPV4:
13+
case AWS_SOCKET_IPV6:
14+
if (port > UINT16_MAX) {
15+
AWS_LOGF_ERROR(
16+
AWS_LS_IO_SOCKET,
17+
"Invalid port=%u for %s. Cannot exceed 65535",
18+
port,
19+
domain == AWS_SOCKET_IPV4 ? "IPv4" : "IPv6");
20+
return aws_raise_error(AWS_IO_SOCKET_INVALID_ADDRESS);
21+
}
22+
break;
23+
24+
case AWS_SOCKET_LOCAL:
25+
/* port is ignored */
26+
break;
27+
28+
case AWS_SOCKET_VSOCK:
29+
/* any 32bit port is legal */
30+
break;
31+
32+
default:
33+
AWS_LOGF_ERROR(AWS_LS_IO_SOCKET, "Cannot validate port for unknown domain=%d", domain);
34+
return aws_raise_error(AWS_IO_SOCKET_INVALID_ADDRESS);
35+
}
36+
return AWS_OP_SUCCESS;
37+
}
38+
39+
int aws_socket_validate_port_for_connect(uint32_t port, enum aws_socket_domain domain) {
40+
if (s_socket_validate_port_for_domain(port, domain)) {
41+
return AWS_OP_ERR;
42+
}
43+
44+
/* additional validation */
45+
switch (domain) {
46+
case AWS_SOCKET_IPV4:
47+
case AWS_SOCKET_IPV6:
48+
if (port == 0) {
49+
AWS_LOGF_ERROR(
50+
AWS_LS_IO_SOCKET,
51+
"Invalid port=%u for %s connections. Must use 1-65535",
52+
port,
53+
domain == AWS_SOCKET_IPV4 ? "IPv4" : "IPv6");
54+
return aws_raise_error(AWS_IO_SOCKET_INVALID_ADDRESS);
55+
}
56+
break;
57+
58+
case AWS_SOCKET_VSOCK:
59+
if (port == (uint32_t)-1) {
60+
AWS_LOGF_ERROR(
61+
AWS_LS_IO_SOCKET, "Invalid port for VSOCK connections. Cannot use VMADDR_PORT_ANY (-1U).");
62+
return aws_raise_error(AWS_IO_SOCKET_INVALID_ADDRESS);
63+
}
64+
break;
65+
66+
default:
67+
/* no extra validation */
68+
break;
69+
}
70+
return AWS_OP_SUCCESS;
71+
}
72+
73+
int aws_socket_validate_port_for_bind(uint32_t port, enum aws_socket_domain domain) {
74+
return s_socket_validate_port_for_domain(port, domain);
75+
}

0 commit comments

Comments
 (0)