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 && LWIP_USE_GET_HOST_BY_NAME_EXTERNAL
33
34 #include "lwip/distributed_net/udp_transmit.h"
35
get_msg_data_len(const struct msghdr * hdr)36 static s32_t get_msg_data_len(const struct msghdr *hdr)
37 {
38 if (hdr->msg_iovlen > MAX_IOV_NUM) {
39 return -1;
40 }
41
42 s32_t data_len = 0;
43 for (int i = 0; i < hdr->msg_iovlen; ++i) {
44 if (hdr->msg_iov[i].iov_len > MAX_UDP_PAYLOAD_LEN) {
45 set_errno(EMSGSIZE);
46 return -1;
47 }
48 data_len += (s32_t)hdr->msg_iov[i].iov_len;
49 if (data_len > MAX_UDP_PAYLOAD_LEN) {
50 set_errno(EMSGSIZE);
51 return -1;
52 }
53 }
54
55 return data_len;
56 }
57
udp_transmit_sendto(int sock,const void * buf,size_t buf_len,const struct sockaddr_in * dest_addr)58 ssize_t udp_transmit_sendto(int sock, const void *buf, size_t buf_len, const struct sockaddr_in *dest_addr)
59 {
60 if (buf_len > MAX_UDP_PAYLOAD_LEN) {
61 set_errno(EMSGSIZE);
62 return -1;
63 }
64
65 udp_data data = {0};
66 (void)memset_s(&data, sizeof(data), 0, sizeof(data));
67 (void)strcpy_s(data.dest_addr, sizeof(data.dest_addr), inet_ntoa(dest_addr->sin_addr));
68 data.dest_port = ntohs(dest_addr->sin_port);
69
70 struct iovec iov[2] = {0};
71 (void)memset_s(iov, sizeof(iov), 0, sizeof(iov));
72 iov[0].iov_base = (void *)&data;
73 iov[0].iov_len = sizeof(data);
74 iov[1].iov_base = (void *)buf;
75 iov[1].iov_len = buf_len;
76
77 struct sockaddr_in transmit_addr = {0};
78 (void)memset_s(&transmit_addr, sizeof(transmit_addr), 0, sizeof(transmit_addr));
79 INIT_SOCK_ADDR(&transmit_addr, LOCAL_SERVER_IP, get_local_udp_server_port());
80
81 struct msghdr send_hdr = {0};
82 (void)memset_s(&send_hdr, sizeof(send_hdr), 0, sizeof(send_hdr));
83 SET_MSG_ADDR(&send_hdr, &transmit_addr, sizeof(transmit_addr));
84 send_hdr.msg_iov = iov;
85 send_hdr.msg_iovlen = 2;
86
87 #if LWIP_DISTRIBUTED_NET_ENABLE_SENDMSG
88 return lwip_sendmsg_internal(sock, &send_hdr, 0);
89 #else
90 return lwip_sendmsg(sock, &send_hdr, 0);
91 #endif
92 }
93
udp_transmit_sendmsg(int sock,const struct msghdr * hdr)94 ssize_t udp_transmit_sendmsg(int sock, const struct msghdr *hdr)
95 {
96 if (get_msg_data_len(hdr) < 0) {
97 return -1;
98 }
99
100 struct sockaddr_in temp_addr_in = {0};
101 (void)memset_s(&temp_addr_in, sizeof(temp_addr_in), 0, sizeof(temp_addr_in));
102 (void)memcpy_s(&temp_addr_in, sizeof(temp_addr_in), hdr->msg_name, MIN(sizeof(temp_addr_in), hdr->msg_namelen));
103
104 udp_data data = {0};
105 (void)memset_s(&data, sizeof(data), 0, sizeof(data));
106 (void)strcpy_s(data.dest_addr, sizeof(data.dest_addr), inet_ntoa(temp_addr_in.sin_addr));
107 data.dest_port = ntohs(temp_addr_in.sin_port);
108
109 u32_t size = sizeof(struct iovec) * (hdr->msg_iovlen + 1);
110 struct iovec *iov = mem_malloc(size);
111 if (iov == NULL) {
112 set_errno(ENOMEM);
113 return -1;
114 }
115 (void)memset_s(iov, size, 0, size);
116 iov[0].iov_base = (void *)&data;
117 iov[0].iov_len = sizeof(data);
118 for (int i = 0; i < hdr->msg_iovlen; ++i) {
119 iov[i + 1].iov_base = hdr->msg_iov[i].iov_base;
120 iov[i + 1].iov_len = hdr->msg_iov[i].iov_len;
121 }
122
123 struct sockaddr_in transmit_addr = {0};
124 (void)memset_s(&transmit_addr, sizeof(transmit_addr), 0, sizeof(transmit_addr));
125 INIT_SOCK_ADDR(&transmit_addr, LOCAL_SERVER_IP, get_local_udp_server_port());
126
127 struct msghdr send_hdr = {0};
128 (void)memset_s(&send_hdr, sizeof(send_hdr), 0, sizeof(send_hdr));
129 SET_MSG_ADDR(&send_hdr, &transmit_addr, sizeof(transmit_addr));
130 send_hdr.msg_iov = iov;
131 send_hdr.msg_iovlen = hdr->msg_iovlen + 1;
132
133 #if LWIP_DISTRIBUTED_NET_ENABLE_SENDMSG
134 ssize_t ret = lwip_sendmsg_internal(sock, &send_hdr, 0);
135 #else
136 ssize_t ret = lwip_sendmsg(sock, &send_hdr, 0);
137 #endif
138 mem_free(iov);
139 return ret;
140 }
141
142 #endif /* LWIP_ENABLE_DISTRIBUTED_NET && LWIP_USE_GET_HOST_BY_NAME_EXTERNAL */
143