1 /*
2 * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved.
3 *
4 * UniProton is licensed under Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 * http://license.coscl.org.cn/MulanPSL2
8 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 * See the Mulan PSL v2 for more details.
12 * Create: 2022-09-21
13 * Description: 网络
14 */
15
16 #include "lwip/opt.h"
17
18 #if LWIP_IFADDRS
19 #if (LWIP_IPV4 || LWIP_IPV6) && LWIP_SOCKET
20 #include "ifaddrs.h"
21
22 #include <stdlib.h>
23
24 #include "lwip/sys.h"
25 #include "lwip/tcpip.h"
26 #include "lwip/priv/sockets_priv.h"
27 #include "lwip/mem.h"
28 #include "lwip/netif.h"
29 #include "lwip/dhcp.h"
30
31 struct TagIfaddrsStorage {
32 struct ifaddrs ifa;
33 union {
34 struct sockaddr sa;
35 struct sockaddr_in s4;
36 #if LWIP_IPV6
37 struct sockaddr_in6 s6;
38 #endif
39 } addr, netmask, dstaddr;
40 U8 name[IFNAMSIZ];
41 };
42
43 struct TagGetifaddrsArg {
44 struct ifaddrs **ifap;
45 sys_sem_t cbCompleted;
46 S32 ret;
47 };
48
49 static S32 g_tcpipInitFinish = 1;
50 static void OsLwipFreeifaddrs(struct ifaddrs *ifa);
OsIfaddrsAddTail(struct ifaddrs ** ifap,struct ifaddrs * ifaddr)51 static void OsIfaddrsAddTail(struct ifaddrs **ifap, struct ifaddrs *ifaddr)
52 {
53 struct ifaddrs *temp = NULL;
54
55 ifaddr->ifa_next = NULL;
56 if (*ifap == NULL) {
57 *ifap = ifaddr;
58 return;
59 }
60
61 for (temp = *ifap; temp->ifa_next != NULL; temp = temp->ifa_next) {
62 /* nothing */
63 }
64
65 temp->ifa_next = ifaddr;
66 }
67
OsNewIfaddrsStorage(void)68 static struct TagIfaddrsStorage *OsNewIfaddrsStorage(void)
69 {
70 struct ifaddrs *ifaddr = NULL;
71 struct TagIfaddrsStorage *ifStorage = (struct TagIfaddrsStorage *)mem_malloc(sizeof(struct TagIfaddrsStorage));
72 if (ifStorage == NULL) {
73 return NULL;
74 }
75 if (memset_s((void *)ifStorage, sizeof(struct TagIfaddrsStorage), 0, sizeof(struct TagIfaddrsStorage)) != EOK) {
76 free(ifStorage);
77 return NULL;
78 }
79 ifaddr = &ifStorage->ifa;
80 ifaddr->ifa_name = ifStorage->name;
81 ifaddr->ifa_addr = &ifStorage->addr.sa;
82 ifaddr->ifa_netmask = &ifStorage->netmask.sa;
83 ifaddr->ifa_dstaddr = &ifStorage->dstaddr.sa;
84 return ifStorage;
85 }
86
OsGetIfaName(struct netif * netif,struct ifaddrs * ifaddr)87 static int OsGetIfaName(struct netif *netif, struct ifaddrs *ifaddr)
88 {
89 int ret;
90
91 if (netif->link_layer_type == LOOPBACK_IF) {
92 ifaddr->ifa_flags |= IFF_LOOPBACK;
93 ret = snprintf_s(ifaddr->ifa_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%.2s", netif->name);
94 } else {
95 ret = snprintf_s(ifaddr->ifa_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s", netif_get_name(netif));
96 }
97
98 return ret;
99 }
100
101 #if LWIP_IPV4
OsGetIpv4Ifaddr(struct netif * netif,struct ifaddrs * ifaddr)102 static int OsGetIpv4Ifaddr(struct netif *netif, struct ifaddrs *ifaddr)
103 {
104 struct sockaddr_in *addrIn = NULL;
105
106 if (netif->flags & NETIF_FLAG_UP) {
107 ifaddr->ifa_flags |= IFF_UP;
108 }
109
110 if (netif->flags & NETIF_FLAG_ETHARP) {
111 ifaddr->ifa_flags = ifaddr->ifa_flags & ((unsigned int)(~IFF_NOARP));
112 } else {
113 ifaddr->ifa_flags |= IFF_NOARP;
114 }
115
116 if (netif->flags & NETIF_FLAG_BROADCAST) {
117 ifaddr->ifa_flags |= IFF_BROADCAST;
118 }
119
120 #if LWIP_DHCP
121 if (dhcp_supplied_address(netif)) {
122 ifaddr->ifa_flags |= IFF_DYNAMIC;
123 }
124 #endif
125
126 #if LWIP_IGMP
127 if (netif->flags & NETIF_FLAG_IGMP) {
128 ifaddr->ifa_flags |= IFF_MULTICAST;
129 }
130 #endif
131
132 if (netif->flags & NETIF_FLAG_LINK_UP) {
133 ifaddr->ifa_flags |= IFF_RUNNING;
134 }
135
136 #if LWIP_HAVE_LOOPIF
137 if (netif->link_layer_type == LOOPBACK_IF) {
138 addrIn = (struct sockaddr_in *)ifaddr->ifa_addr;
139 addrIn->sin_family = AF_INET;
140 addrIn->sin_addr.s_addr = ((ip4_addr_t *)&netif->ip_addr)->addr;
141 } else
142 #endif
143 {
144 addrIn = (struct sockaddr_in *)ifaddr->ifa_addr;
145 addrIn->sin_family = AF_INET;
146 addrIn->sin_addr.s_addr = ((ip4_addr_t *)&netif->ip_addr)->addr;
147
148 addrIn = (struct sockaddr_in *)ifaddr->ifa_netmask;
149 addrIn->sin_family = AF_INET;
150 addrIn->sin_addr.s_addr = ((ip4_addr_t *)&netif->netmask)->addr;
151
152 addrIn = (struct sockaddr_in *)ifaddr->ifa_broadaddr;
153 addrIn->sin_family = AF_INET;
154 addrIn->sin_addr.s_addr = (((ip4_addr_t *)&netif->ip_addr)->addr & ((ip4_addr_t *)&netif->netmask)->addr) |
155 ~((ip4_addr_t *)&netif->netmask)->addr;
156 }
157
158 return OsGetIfaName(netif, ifaddr);
159 }
160 #endif /* LWIP_IPV4 */
161
162 #if LWIP_IPV6
163 /* Stack support to retrieve the below flags for ipv6
164 IFF_UP
165 IFF_MULTICAST
166 IFF_RUNNING
167 IFF_LOOPBACK
168 */
OsGetIpv6Ifaddr(struct netif * netif,struct ifaddrs * ifaddr,int tmp_index)169 static int OsGetIpv6Ifaddr(struct netif *netif, struct ifaddrs *ifaddr, int tmp_index)
170 {
171 struct sockaddr_in6 *addrIn6 = NULL;
172
173 /* As of now supports the below falgs only */
174 if (netif->flags & NETIF_FLAG_UP) {
175 ifaddr->ifa_flags |= IFF_UP;
176 }
177
178 #if LWIP_IPV6_MLD
179 if (netif->flags & NETIF_FLAG_MLD6) {
180 ifaddr->ifa_flags |= IFF_MULTICAST;
181 }
182 #endif
183
184 if (netif->flags & NETIF_FLAG_LINK_UP) {
185 ifaddr->ifa_flags |= IFF_RUNNING;
186 }
187
188 addrIn6 = (struct sockaddr_in6 *)ifaddr->ifa_addr;
189 addrIn6->sin6_family = AF_INET6;
190 inet6_addr_from_ip6addr(&addrIn6->sin6_addr, (ip6_addr_t *)&netif->ip6_addr[tmp_index]);
191
192 return OsGetIfaName(netif, ifaddr);
193 }
194 #endif
195
OsGetIfaddrsInternal(struct TagGetifaddrsArg * arg)196 static void OsGetIfaddrsInternal(struct TagGetifaddrsArg *arg)
197 {
198 struct netif *netif = NULL;
199 struct ifaddrs *ifaddr = NULL;
200 struct TagIfaddrsStorage *ifStorage = NULL;
201
202 #if LWIP_IPV6
203 int n;
204 #endif
205
206 arg->ret = ENOMEM;
207 for (netif = netif_list; netif != NULL; netif = netif->next) {
208 #if LWIP_IPV4
209 ifStorage = OsNewIfaddrsStorage();
210 if (ifStorage == NULL) {
211 /* ifap is assigned to NULL in getifaddrs, so garbage value will not be there */
212 OsLwipFreeifaddrs(*(arg->ifap));
213 arg->ret = ENOMEM;
214 #if !LWIP_TCPIP_CORE_LOCKING
215 sys_sem_signal(&arg->cbCompleted);
216 #endif
217 return;
218 }
219
220 /* if get one or more netif info, then getifaddrs return 0(OK) */
221 arg->ret = 0;
222 ifaddr = &ifStorage->ifa;
223 (void)OsGetIpv4Ifaddr(netif, ifaddr);
224 OsIfaddrsAddTail(arg->ifap, ifaddr);
225 #endif /* LWIP_IPV4 */
226 #if LWIP_IPV6
227 for (n = 0; n < LWIP_IPV6_NUM_ADDRESSES; n++) {
228 if ((netif->ip6_addr_state[n] & IP6_ADDR_VALID) == 0) {
229 continue;
230 }
231 ifStorage = OsNewIfaddrsStorage();
232 if (ifStorage == NULL) {
233 /* ifap is assigned to NULL in getifaddrs, so garbage value will not be there */
234 OsLwipFreeifaddrs(*(arg->ifap));
235 arg->ret = ENOMEM;
236 #if !LWIP_TCPIP_CORE_LOCKING
237 sys_sem_signal(&arg->cbCompleted);
238 #endif
239 return;
240 }
241
242 /* if get one or more netif info, then getifaddrs return 0(OK) */
243 arg->ret = 0;
244 ifaddr = &ifStorage->ifa;
245 (void)OsGetIpv6Ifaddr(netif, ifaddr, n);
246 OsIfaddrsAddTail(arg->ifap, ifaddr);
247 }
248 #endif
249 }
250
251 #if !LWIP_TCPIP_CORE_LOCKING
252 sys_sem_signal(&arg->cbCompleted);
253 #endif
254 return;
255 }
256
OsLwipGetifaddrs(struct ifaddrs ** ifap)257 static int OsLwipGetifaddrs(struct ifaddrs **ifap)
258 {
259 struct TagGetifaddrsArg arg;
260
261 LWIP_ERROR("OsLwipGetifaddrs : ifap is NULL", (ifap != NULL), return ERR_ARG);
262 *ifap = NULL;
263
264 if (!g_tcpipInitFinish) {
265 set_errno(EACCES);
266 return -1;
267 }
268 arg.ret = 0;
269 arg.ifap = ifap;
270
271 #if LWIP_TCPIP_CORE_LOCKING
272 LOCK_TCPIP_CORE();
273 OsGetIfaddrsInternal(&arg);
274 UNLOCK_TCPIP_CORE();
275 #else
276
277 if (sys_sem_new(&arg.cbCompleted, 0) != ERR_OK) {
278 set_errno(ENOMEM);
279 return -1;
280 }
281
282 tcpip_callback((tcpip_callback_fn)OsGetIfaddrsInternal, &arg);
283 (void)sys_arch_sem_wait(&arg.cbCompleted, 0);
284 sys_sem_free(&arg.cbCompleted);
285 #endif
286
287 if (arg.ret != 0) {
288 set_errno(arg.ret);
289 *ifap = NULL;
290 return -1;
291 }
292
293 return 0;
294 }
295
OsFreeifaddrsIteration(struct ifaddrs * ifa)296 static void OsFreeifaddrsIteration(struct ifaddrs *ifa)
297 {
298 if (ifa == NULL) {
299 return;
300 }
301
302 if (ifa->ifa_next != NULL) {
303 OsFreeifaddrsIteration(ifa->ifa_next);
304 }
305
306 mem_free(ifa);
307 }
308
OsLwipFreeifaddrs(struct ifaddrs * ifa)309 static void OsLwipFreeifaddrs(struct ifaddrs *ifa)
310 {
311 OsFreeifaddrsIteration(ifa);
312 }
313
getifaddrs(struct ifaddrs ** ifap)314 int getifaddrs(struct ifaddrs **ifap)
315 {
316 return OsLwipGetifaddrs(ifap);
317 }
318
freeifaddrs(struct ifaddrs * ifa)319 void freeifaddrs(struct ifaddrs *ifa)
320 {
321 OsLwipFreeifaddrs(ifa);
322 }
323
324 #endif /* (LWIP_IPV4 || LWIP_IPV6) && LWIP_SOCKET */
325 #endif /* LWIP_IFADDRS */
326