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