• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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