• 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/opt.h"
31 
32 #if LWIP_ENABLE_DISTRIBUTED_NET
33 
34 #include "lwip/distributed_net/distributed_net_core.h"
35 #include "lwip/distributed_net/distributed_net_utils.h"
36 #include "lwip/distributed_net/udp_transmit.h"
37 #include "lwip/priv/sockets_priv.h"
38 
distributed_net_connect(int sock,const struct sockaddr * addr,socklen_t addr_len)39 int distributed_net_connect(int sock, const struct sockaddr *addr, socklen_t addr_len)
40 {
41   CHECK_PARA(SOCKET_TO_INDEX(sock) >= 0 && SOCKET_TO_INDEX(sock) < NUM_SOCKETS, EBADF);
42   CHECK_PARA(addr != NULL, EINVAL);
43   CHECK_PARA(addr_len > 0, EINVAL);
44 
45   struct sockaddr_in addr_in = {0};
46   (void)memset_s(&addr_in, sizeof(addr_in), 0, sizeof(addr_in));
47   (void)memcpy_s(&addr_in, sizeof(addr_in), addr, MIN(sizeof(addr_in), addr_len));
48   if (is_no_proxy_network_segment(&addr_in)) {
49     return lwip_connect_internal(sock, addr, addr_len);
50   }
51 
52   (void)memset_s(&addr_in, sizeof(addr_in), 0, sizeof(addr_in));
53   INIT_SOCK_ADDR(&addr_in, LOCAL_SERVER_IP, get_local_tcp_server_port());
54   if (lwip_connect_internal(sock, (struct sockaddr *)&addr_in, sizeof(addr_in)) < 0) {
55     if (get_errno() != EINPROGRESS) {
56       return -1;
57     }
58   }
59   set_distributed_net_socket(sock);
60 
61   (void)memset_s(&addr_in, sizeof(addr_in), 0, sizeof(addr_in));
62   (void)memcpy_s(&addr_in, sizeof(addr_in), addr, MIN(sizeof(addr_in), addr_len));
63 
64   tcp_connect_data data = {0};
65   (void)memset_s(&data, sizeof(data), 0, sizeof(data));
66   (void)strcpy_s(data.dest_addr, sizeof(data.dest_addr), inet_ntoa(addr_in.sin_addr));
67   data.dest_port = ntohs(addr_in.sin_port);
68 
69   if (lwip_send(sock, &data, sizeof(data), 0) < 0) {
70     reset_distributed_net_socket(sock);
71     return -1;
72   }
73   return 0;
74 }
75 
distributed_net_close(int sock)76 int distributed_net_close(int sock)
77 {
78   CHECK_PARA(SOCKET_TO_INDEX(sock) >= 0 && SOCKET_TO_INDEX(sock) < NUM_SOCKETS, EBADF);
79 
80   reset_distributed_net_socket(sock);
81   return lwip_close_internal(sock);
82 }
83 
84 #if LWIP_USE_GET_HOST_BY_NAME_EXTERNAL
85 typedef union {
86   struct sockaddr sa;
87 #if LWIP_IPV6
88   struct sockaddr_in6 sin6;
89 #endif /* LWIP_IPV6 */
90 #if LWIP_IPV4
91   struct sockaddr_in sin;
92 #endif /* LWIP_IPV4 */
93 } aligned_sockaddr;
94 
distributed_net_sendto(int sock,const void * buf,size_t buf_len,int flags,const struct sockaddr * addr,socklen_t addr_len)95 ssize_t distributed_net_sendto(int sock, const void *buf, size_t buf_len, int flags, const struct sockaddr *addr,
96                                socklen_t addr_len)
97 {
98   CHECK_PARA(SOCKET_TO_INDEX(sock) >= 0 && SOCKET_TO_INDEX(sock) < NUM_SOCKETS, EBADF);
99   CHECK_PARA(buf != NULL, EINVAL);
100   CHECK_PARA(buf_len > 0, EINVAL);
101 
102   int type = 0;
103   socklen_t type_len = sizeof(type);
104   if (lwip_getsockopt(sock, SOL_SOCKET, SO_TYPE, (void *)&type, &type_len) < 0) {
105     return -1;
106   }
107 
108   if (type != SOCK_DGRAM) {
109     return lwip_sendto_internal(sock, buf, buf_len, flags, addr, addr_len);
110   }
111 
112   struct sockaddr_in addr_in = {0};
113   (void)memset_s(&addr_in, sizeof(addr_in), 0, sizeof(addr_in));
114   if (addr != NULL && addr_len != 0) {
115     (void)memcpy_s(&addr_in, sizeof(addr_in), addr, MIN(sizeof(addr_in), addr_len));
116   }
117 
118   if (IS_LOCAL_UDP_SERVER_ADDR(&addr_in)) {
119     set_errno(EPERM);
120     return -1;
121   }
122 
123   if (is_no_proxy_network_segment(&addr_in)) {
124     return lwip_sendto_internal(sock, buf, buf_len, flags, addr, addr_len);
125   }
126 
127   if (!IS_DNS_PORT(addr_in)) {
128     set_errno(EPERM);
129     return -1;
130   }
131 
132   ssize_t ret = udp_transmit_sendto(sock, buf, buf_len, &addr_in);
133   return ret > 0 ? UDP_PAYLOAD_LEN(ret) : -1;
134 }
135 
136 #if LWIP_DISTRIBUTED_NET_ENABLE_SENDMSG
distributed_net_sendmsg(int sock,const struct msghdr * hdr,int flags)137 ssize_t distributed_net_sendmsg(int sock, const struct msghdr *hdr, int flags)
138 {
139   CHECK_PARA(SOCKET_TO_INDEX(sock) >= 0 && SOCKET_TO_INDEX(sock) < NUM_SOCKETS, EBADF);
140   CHECK_PARA(hdr != NULL, EINVAL);
141   CHECK_PARA(hdr->msg_iov != NULL, EINVAL);
142   CHECK_PARA(hdr->msg_iovlen > 0, EINVAL);
143 
144   int type = 0;
145   socklen_t type_len = sizeof(type);
146   if (lwip_getsockopt(sock, SOL_SOCKET, SO_TYPE, (void *)&type, &type_len) < 0) {
147     return -1;
148   }
149 
150   if (type != SOCK_DGRAM) {
151     return lwip_sendmsg_internal(sock, hdr, flags);
152   }
153 
154   const struct sockaddr *addr = (const struct sockaddr *)hdr->msg_name;
155   socklen_t addr_len = hdr->msg_namelen;
156 
157   struct sockaddr_in addr_in = {0};
158   (void)memset_s(&addr_in, sizeof(addr_in), 0, sizeof(addr_in));
159   if (addr != NULL && addr_len != 0) {
160     (void)memcpy_s(&addr_in, sizeof(addr_in), addr, MIN(sizeof(addr_in), addr_len));
161   }
162 
163   if (IS_LOCAL_UDP_SERVER_ADDR(&addr_in)) {
164     set_errno(EPERM);
165     return -1;
166   }
167 
168   if (is_no_proxy_network_segment(&addr_in)) {
169     return lwip_sendmsg_internal(sock, hdr, flags);
170   }
171 
172   if (!IS_DNS_PORT(addr_in)) {
173     set_errno(EPERM);
174     return -1;
175   }
176 
177   ssize_t ret = udp_transmit_sendmsg(sock, hdr);
178   return ret > 0 ? UDP_PAYLOAD_LEN(ret) : -1;
179 }
180 #endif /* LWIP_DISTRIBUTED_NET_ENABLE_SENDMSG */
181 
distributed_net_recvfrom(int sock,void * buf,size_t buf_len,int flags,struct sockaddr * from,socklen_t * from_len)182 ssize_t distributed_net_recvfrom(int sock, void *buf, size_t buf_len, int flags, struct sockaddr *from,
183                                  socklen_t *from_len)
184 {
185   CHECK_PARA(SOCKET_TO_INDEX(sock) >= 0 && SOCKET_TO_INDEX(sock) < NUM_SOCKETS, EBADF);
186   CHECK_PARA(buf != NULL, EINVAL);
187   CHECK_PARA(buf_len > 0, EINVAL);
188 
189   int type = 0;
190   socklen_t type_len = sizeof(type);
191   if (lwip_getsockopt(sock, SOL_SOCKET, SO_TYPE, (void *)&type, &type_len) < 0) {
192     return -1;
193   }
194 
195   if (type != SOCK_DGRAM) {
196     return lwip_recvfrom_internal(sock, buf, buf_len, flags, from, from_len);
197   }
198 
199   size_t new_buf_len = buf_len + sizeof(udp_data);
200   void *new_buf = mem_malloc(new_buf_len);
201   if (new_buf == NULL) {
202     set_errno(ENOMEM);
203     return -1;
204   }
205 
206   aligned_sockaddr addr_from = {0};
207   socklen_t addr_from_len = sizeof(addr_from);
208   ssize_t ret =
209       lwip_recvfrom_internal(sock, new_buf, new_buf_len, flags, (struct sockaddr *)&addr_from, &addr_from_len);
210   if (ret <= 0) {
211     mem_free(new_buf);
212     return ret;
213   }
214 
215   if (!IS_LOCAL_UDP_SERVER_ADDR((struct sockaddr_in *)(&addr_from))) {
216     (void)memcpy_s(buf, buf_len, new_buf, ret);
217     if (from != NULL && from_len != NULL) {
218       if (*from_len > addr_from_len) {
219         *from_len = addr_from_len;
220       }
221       (void)memcpy_s(from, *from_len, &addr_from, *from_len);
222       mem_free(new_buf);
223       return ret;
224     }
225   }
226 
227   if (ret <= sizeof(udp_data)) {
228     mem_free(new_buf);
229     set_errno(EINVAL);
230     return -1;
231   }
232 
233   udp_data *data = (udp_data *)new_buf;
234   (void)memcpy_s(buf, buf_len, data->payload, ret - sizeof(udp_data));
235   if (from != NULL && from_len != NULL) {
236     (void)memcpy_s(from, *from_len, &addr_from, MIN(addr_from_len, *from_len));
237     if (*from_len >= sizeof(struct sockaddr_in) - SIN_ZERO_LEN) {
238       struct sockaddr_in *temp_addr = (struct sockaddr_in *)from;
239       INIT_SOCK_ADDR(temp_addr, data->dest_addr, data->dest_port);
240       if (*from_len > sizeof(struct sockaddr_in)) {
241         *from_len = sizeof(struct sockaddr_in);
242       }
243     }
244   }
245 
246   mem_free(new_buf);
247   return ret - (ssize_t)sizeof(udp_data);
248 }
249 #endif /* LWIP_USE_GET_HOST_BY_NAME_EXTERNAL */
250 
251 #endif /* LWIP_ENABLE_DISTRIBUTED_NET */
252