1 /* Copyright (c) 2021-2021 Huawei Device Co., Ltd. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without modification,
4 * are permitted provided that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain the above copyright notice, this list of
7 * conditions and the following disclaimer.
8 *
9 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
10 * of conditions and the following disclaimer in the documentation and/or other materials
11 * provided with the distribution.
12 *
13 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
14 * to endorse or promote products derived from this software without specific prior written
15 * permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include "lwip/sockets.h"
31 #include "lwip/priv/tcpip_priv.h"
32 #include "lwip/priv/sockets_priv.h"
33 #include "lwip/prot/dhcp.h"
34 #include "lwip/dhcp.h"
35 #include "lwip/if_api.h"
36 #include <errno.h>
37
38 #if LWIP_ENABLE_DISTRIBUTED_NET
39
40 #include "lwip/distributed_net/distributed_net_core.h"
41 #include "lwip/distributed_net/distributed_net_utils.h"
42 #include "lwip/distributed_net/udp_transmit.h"
43 #include "lwip/priv/sockets_priv.h"
44
distributed_net_connect(int sock,const struct sockaddr * addr,socklen_t addr_len)45 int distributed_net_connect(int sock, const struct sockaddr *addr, socklen_t addr_len)
46 {
47 CHECK_PARA(SOCKET_TO_INDEX(sock) >= 0 && SOCKET_TO_INDEX(sock) < NUM_SOCKETS, EBADF);
48 CHECK_PARA(addr != NULL, EINVAL);
49 CHECK_PARA(addr_len > 0, EINVAL);
50
51 struct sockaddr_in addr_in = {0};
52 (void)memset_s(&addr_in, sizeof(addr_in), 0, sizeof(addr_in));
53 (void)memcpy_s(&addr_in, sizeof(addr_in), addr, MIN(sizeof(addr_in), addr_len));
54 if (is_no_proxy_network_segment(&addr_in)) {
55 return lwip_connect_internal(sock, addr, addr_len);
56 }
57
58 (void)memset_s(&addr_in, sizeof(addr_in), 0, sizeof(addr_in));
59 INIT_SOCK_ADDR(&addr_in, LOCAL_SERVER_IP, get_local_tcp_server_port());
60 #if (defined(EMUI_WEB_CLIENT))
61 DISTRIBUTED_NET_START_TCP_SERVER();
62 #endif
63 if (lwip_connect_internal(sock, (struct sockaddr *)&addr_in, sizeof(addr_in)) < 0) {
64 if (errno != EINPROGRESS) {
65 return -1;
66 }
67 }
68 set_distributed_net_socket(sock);
69
70 (void)memset_s(&addr_in, sizeof(addr_in), 0, sizeof(addr_in));
71 (void)memcpy_s(&addr_in, sizeof(addr_in), addr, MIN(sizeof(addr_in), addr_len));
72
73 tcp_connect_data data = {0};
74 (void)memset_s(&data, sizeof(data), 0, sizeof(data));
75 (void)strcpy_s(data.dest_addr, sizeof(data.dest_addr), inet_ntoa(addr_in.sin_addr));
76 data.dest_port = ntohs(addr_in.sin_port);
77
78 if (lwip_send(sock, &data, sizeof(data), 0) < 0) {
79 reset_distributed_net_socket(sock);
80 return -1;
81 }
82 return 0;
83 }
84
distributed_net_close(int sock)85 int distributed_net_close(int sock)
86 {
87 CHECK_PARA(SOCKET_TO_INDEX(sock) >= 0 && SOCKET_TO_INDEX(sock) < NUM_SOCKETS, EBADF);
88
89 reset_distributed_net_socket(sock);
90 return lwip_close_internal(sock);
91 }
92
93 #if LWIP_USE_GET_HOST_BY_NAME_EXTERNAL
94 typedef union {
95 struct sockaddr sa;
96 #if LWIP_IPV6
97 struct sockaddr_in6 sin6;
98 #endif /* LWIP_IPV6 */
99 #if LWIP_IPV4
100 struct sockaddr_in sin;
101 #endif /* LWIP_IPV4 */
102 } aligned_sockaddr;
103
distributed_net_sendto(int sock,const void * buf,size_t buf_len,int flags,const struct sockaddr * addr,socklen_t addr_len)104 ssize_t distributed_net_sendto(int sock, const void *buf, size_t buf_len, int flags, const struct sockaddr *addr,
105 socklen_t addr_len)
106 {
107 CHECK_PARA(SOCKET_TO_INDEX(sock) >= 0 && SOCKET_TO_INDEX(sock) < NUM_SOCKETS, EBADF);
108 CHECK_PARA(buf != NULL, EINVAL);
109 CHECK_PARA(buf_len > 0, EINVAL);
110
111 int type = 0;
112 socklen_t type_len = sizeof(type);
113 if (lwip_getsockopt(sock, SOL_SOCKET, SO_TYPE, (void *)&type, &type_len) < 0) {
114 return -1;
115 }
116
117 if (type != SOCK_DGRAM) {
118 return lwip_sendto_internal(sock, buf, buf_len, flags, addr, addr_len);
119 }
120
121 struct sockaddr_in addr_in = {0};
122 (void)memset_s(&addr_in, sizeof(addr_in), 0, sizeof(addr_in));
123 if (addr != NULL && addr_len != 0) {
124 (void)memcpy_s(&addr_in, sizeof(addr_in), addr, MIN(sizeof(addr_in), addr_len));
125 }
126
127 if (IS_LOCAL_UDP_SERVER_ADDR(&addr_in)) {
128 set_errno(EPERM);
129 return -1;
130 }
131
132 if (is_no_proxy_network_segment(&addr_in)) {
133 return lwip_sendto_internal(sock, buf, buf_len, flags, addr, addr_len);
134 }
135
136 if (!IS_DNS_PORT(addr_in)) {
137 set_errno(EPERM);
138 return -1;
139 }
140
141 ssize_t ret = udp_transmit_sendto(sock, buf, buf_len, &addr_in);
142 return ret > 0 ? UDP_PAYLOAD_LEN(ret) : -1;
143 }
144
145 #if LWIP_DISTRIBUTED_NET_ENABLE_SENDMSG
distributed_net_sendmsg(int sock,const struct msghdr * hdr,int flags)146 ssize_t distributed_net_sendmsg(int sock, const struct msghdr *hdr, int flags)
147 {
148 CHECK_PARA(SOCKET_TO_INDEX(sock) >= 0 && SOCKET_TO_INDEX(sock) < NUM_SOCKETS, EBADF);
149 CHECK_PARA(hdr != NULL, EINVAL);
150 CHECK_PARA(hdr->msg_iov != NULL, EINVAL);
151 CHECK_PARA(hdr->msg_iovlen > 0, EINVAL);
152
153 int type = 0;
154 socklen_t type_len = sizeof(type);
155 if (lwip_getsockopt(sock, SOL_SOCKET, SO_TYPE, (void *)&type, &type_len) < 0) {
156 return -1;
157 }
158
159 if (type != SOCK_DGRAM) {
160 return lwip_sendmsg_internal(sock, hdr, flags);
161 }
162
163 const struct sockaddr *addr = (const struct sockaddr *)hdr->msg_name;
164 socklen_t addr_len = hdr->msg_namelen;
165
166 struct sockaddr_in addr_in = {0};
167 (void)memset_s(&addr_in, sizeof(addr_in), 0, sizeof(addr_in));
168 if (addr != NULL && addr_len != 0) {
169 (void)memcpy_s(&addr_in, sizeof(addr_in), addr, MIN(sizeof(addr_in), addr_len));
170 }
171
172 if (IS_LOCAL_UDP_SERVER_ADDR(&addr_in)) {
173 set_errno(EPERM);
174 return -1;
175 }
176
177 if (is_no_proxy_network_segment(&addr_in)) {
178 return lwip_sendmsg_internal(sock, hdr, flags);
179 }
180
181 if (!IS_DNS_PORT(addr_in)) {
182 set_errno(EPERM);
183 return -1;
184 }
185
186 ssize_t ret = udp_transmit_sendmsg(sock, hdr);
187 return ret > 0 ? UDP_PAYLOAD_LEN(ret) : -1;
188 }
189 #endif /* LWIP_DISTRIBUTED_NET_ENABLE_SENDMSG */
190
distributed_net_recvfrom(int sock,void * buf,size_t buf_len,int flags,struct sockaddr * from,socklen_t * from_len)191 ssize_t distributed_net_recvfrom(int sock, void *buf, size_t buf_len, int flags, struct sockaddr *from,
192 socklen_t *from_len)
193 {
194 CHECK_PARA(SOCKET_TO_INDEX(sock) >= 0 && SOCKET_TO_INDEX(sock) < NUM_SOCKETS, EBADF);
195 CHECK_PARA(buf != NULL, EINVAL);
196 CHECK_PARA(buf_len > 0, EINVAL);
197
198 int type = 0;
199 socklen_t type_len = sizeof(type);
200 if (lwip_getsockopt(sock, SOL_SOCKET, SO_TYPE, (void *)&type, &type_len) < 0) {
201 return -1;
202 }
203
204 if (type != SOCK_DGRAM) {
205 return lwip_recvfrom_internal(sock, buf, buf_len, flags, from, from_len);
206 }
207
208 size_t new_buf_len = buf_len + sizeof(udp_data);
209 void *new_buf = mem_malloc(new_buf_len);
210 if (new_buf == NULL) {
211 set_errno(ENOMEM);
212 return -1;
213 }
214
215 aligned_sockaddr addr_from = {0};
216 socklen_t addr_from_len = sizeof(addr_from);
217 ssize_t ret =
218 lwip_recvfrom_internal(sock, new_buf, new_buf_len, flags, (struct sockaddr *)&addr_from, &addr_from_len);
219 if (ret <= 0) {
220 mem_free(new_buf);
221 return ret;
222 }
223
224 if (!IS_LOCAL_UDP_SERVER_ADDR((struct sockaddr_in *)(&addr_from))) {
225 (void)memcpy_s(buf, buf_len, new_buf, ret);
226 if (from != NULL && from_len != NULL) {
227 if (*from_len > addr_from_len) {
228 *from_len = addr_from_len;
229 }
230 (void)memcpy_s(from, *from_len, &addr_from, *from_len);
231 mem_free(new_buf);
232 return ret;
233 }
234 }
235
236 if (ret <= sizeof(udp_data)) {
237 mem_free(new_buf);
238 set_errno(EINVAL);
239 return -1;
240 }
241
242 udp_data *data = (udp_data *)new_buf;
243 (void)memcpy_s(buf, buf_len, data->payload, ret - sizeof(udp_data));
244 if (from != NULL && from_len != NULL) {
245 (void)memcpy_s(from, *from_len, &addr_from, MIN(addr_from_len, *from_len));
246 if (*from_len >= sizeof(struct sockaddr_in) - SIN_ZERO_LEN) {
247 struct sockaddr_in *temp_addr = (struct sockaddr_in *)from;
248 INIT_SOCK_ADDR(temp_addr, data->dest_addr, data->dest_port);
249 if (*from_len > sizeof(struct sockaddr_in)) {
250 *from_len = sizeof(struct sockaddr_in);
251 }
252 }
253 }
254
255 mem_free(new_buf);
256 return ret - (ssize_t)sizeof(udp_data);
257 }
258 #endif /* LWIP_USE_GET_HOST_BY_NAME_EXTERNAL */
259
260 #endif /* LWIP_ENABLE_DISTRIBUTED_NET */
261