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