1 //
2 //
3 // Copyright 2022 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18
19 #include <grpc/support/port_platform.h>
20
21 #include "src/core/lib/iomgr/port.h"
22
23 #ifdef GRPC_POSIX_SOCKET_TCP_SERVER_UTILS_COMMON
24
25 #ifdef HAVE_LIBSYSTEMD
26 #include <systemd/sd-daemon.h>
27 #endif
28
29 #include "src/core/lib/address_utils/sockaddr_utils.h"
30 #include "src/core/lib/iomgr/resolve_address.h"
31 #include "src/core/lib/iomgr/sockaddr.h"
32 #include "src/core/lib/iomgr/systemd_utils.h"
33
34 #ifdef HAVE_LIBSYSTEMD
set_matching_sd_unix_fd(grpc_tcp_server * s,const grpc_resolved_address * addr,const int fd_start,const int n)35 bool set_matching_sd_unix_fd(grpc_tcp_server* s,
36 const grpc_resolved_address* addr,
37 const int fd_start, const int n) {
38 absl::StatusOr<std::string> addr_name = grpc_sockaddr_to_string(addr, true);
39 for (int i = fd_start; i < fd_start + n; i++) {
40 if (sd_is_socket_unix(i, SOCK_STREAM, 1, addr_name.value().c_str(), 0)) {
41 grpc_tcp_server_set_pre_allocated_fd(s, i);
42 return true;
43 }
44 }
45 return false;
46 }
47
set_matching_sd_inet_fd(grpc_tcp_server * s,const grpc_resolved_address * addr,const int family,const int port,const int fd_start,const int n)48 bool set_matching_sd_inet_fd(grpc_tcp_server* s,
49 const grpc_resolved_address* addr,
50 const int family, const int port,
51 const int fd_start, const int n) {
52 for (int i = fd_start; i < fd_start + n; i++) {
53 int r_inet = sd_is_socket_inet(i, family, SOCK_STREAM, 1, (uint16_t)port);
54 int r_addr = sd_is_socket_sockaddr(
55 i, SOCK_STREAM,
56 reinterpret_cast<grpc_sockaddr*>(const_cast<char*>(addr->addr)),
57 addr->len, 1);
58
59 if (r_inet > 0 && r_addr > 0) {
60 grpc_tcp_server_set_pre_allocated_fd(s, i);
61 return true;
62 }
63 }
64 return false;
65 }
66
set_matching_sd_fds(grpc_tcp_server * s,const grpc_resolved_address * addr,int requested_port)67 void set_matching_sd_fds(grpc_tcp_server* s, const grpc_resolved_address* addr,
68 int requested_port) {
69 int n = sd_listen_fds(0);
70 if (n <= 0) {
71 return;
72 }
73
74 int fd_start = SD_LISTEN_FDS_START;
75 grpc_resolved_address addr6_v4mapped;
76
77 if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
78 addr = &addr6_v4mapped;
79 }
80
81 int family = grpc_sockaddr_get_family(addr);
82 int port = grpc_sockaddr_get_port(addr);
83
84 if (family == AF_UNIX) {
85 set_matching_sd_unix_fd(s, addr, fd_start, n);
86 } else {
87 if (grpc_sockaddr_is_wildcard(addr, &requested_port)) {
88 grpc_resolved_address wild4;
89 grpc_resolved_address wild6;
90 grpc_resolved_address wildcard_addrs[2];
91
92 grpc_sockaddr_make_wildcards(requested_port, &wild4, &wild6);
93 wildcard_addrs[0] = wild4;
94 wildcard_addrs[1] = wild6;
95
96 for (grpc_resolved_address addr_w : wildcard_addrs) {
97 int family_w = grpc_sockaddr_get_family(&addr_w);
98 int port_w = grpc_sockaddr_get_port(&addr_w);
99 if (set_matching_sd_inet_fd(s, &addr_w, family_w, port_w, fd_start,
100 n)) {
101 return;
102 }
103 }
104 return;
105 }
106
107 set_matching_sd_inet_fd(s, addr, family, port, fd_start, n);
108 }
109 }
110 #else
set_matching_sd_fds(GRPC_UNUSED grpc_tcp_server * s,GRPC_UNUSED const grpc_resolved_address * addr,GRPC_UNUSED int requested_port)111 void set_matching_sd_fds(GRPC_UNUSED grpc_tcp_server* s,
112 GRPC_UNUSED const grpc_resolved_address* addr,
113 GRPC_UNUSED int requested_port) {}
114 #endif // HAVE_LIBSYSTEMD
115
116 #endif // GRPC_POSIX_SOCKET_TCP_SERVER_UTILS_COMMON
117