• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  * Description: implementation for ip6 in ip4
15  * Author: NA
16  * Create: 2020
17  */
18 
19 #include "lwip/opt.h"
20 
21 #if LWIP_IP6IN4
22 #include "lwip/ip6in4.h"
23 #include "lwip/pbuf.h"
24 #include "lwip/netif.h"
25 #include "lwip/ip.h"
26 #include "lwip/icmp.h"
27 #include "lwip/stats.h"
28 #include "lwip/lwip_rpl.h"
29 #include "lwip/etharp.h"
30 #include "lwip/netifapi.h"
31 #include "lwip/udp.h"
32 #include "lwip/tcp.h"
33 #include "lwip/inet_chksum.h"
34 #if LWIP_LOWPOWER
35 #include "lwip/lowpower.h"
36 #endif
37 
38 #include "lwip/ip6in4_api.h"
39 
40 #if (LWIP_IPV4 == 0) || (LWIP_IPV6 == 0) || (LWIP_RIPPLE == 0)
41 #error "it should enable the ipv4, ipv6 and ripple module before using ip6in4."
42 #endif
43 
44 #define IP6IN4_PKT_HANDLED       (1)
45 #define IP6IN4_PKT_NOT_HANDLED   (0)
46 
47 #define IP6IN4_RET_FAIL  (-1)
48 #define IP6IN4_RET_OK    (0)
49 #define IP6IN4_RET_ERR   (1)
50 
51 #define IP6IN4_V6_VERSION 6
52 #define IP6IN4_NETIF_NAME_LEN_MIN 2
53 
54 #define LWIP_IP6IN4_ENTRY_ADD_UPDATE 1
55 #define LWIP_IP6IN4_ENTRY_DELETE 2
56 #define LWIP_IP6IN4_ENTRY_SYNC 3
57 
58 typedef struct {
59   const char *name;
60   uint8_t len;
61   uint8_t mbr_cnt;
62 } ip6in4_init_arg;
63 
64 typedef struct {
65   const lwip_ip6in4_entry_t *entry;
66   uint8_t cnt;
67   uint8_t evt;
68 } ip6in4_entry_update_arg;
69 
70 typedef struct {
71   lwip_ip6in4_entry_t *entry;
72   uint8_t cnt;
73   uint8_t ret_cnt;
74 } ip6in4_entry_all_arg;
75 
76 typedef struct {
77   lwip_ip6in4_entry_t *entry;
78   const char *mac;
79   uint8_t len;
80 } ip6in4_entry_mac_arg;
81 
82 static struct netif *g_ip6in4_nif;
83 static ip6in4_entry_t *g_ip6in4_entry;
84 static uint8_t g_ip6in4_entry_size;
85 static uint8_t g_ip6in4_entry_cnt;
86 static uint8_t g_ip6in4_inited;
87 
88 static void
ip6in4_entry_on_remove(ip6in4_entry_t * entry)89 ip6in4_entry_on_remove(ip6in4_entry_t *entry)
90 {
91   /* arp clear */
92   (void)etharp_delete_arp_entry(g_ip6in4_nif, &entry->ip4);
93 }
94 
95 static err_t
ip6in4_entry_remove(ip6in4_entry_t * entry)96 ip6in4_entry_remove(ip6in4_entry_t *entry)
97 {
98   if ((entry == NULL) || (entry->in_use == lwIP_FALSE)) {
99     return ERR_ARG;
100   }
101 
102   /* here trigger the remove event */
103   ip6in4_entry_on_remove(entry);
104 
105   if (g_ip6in4_entry_cnt > 0) {
106     g_ip6in4_entry_cnt--;
107   }
108 
109   (void)memset_s(entry, sizeof(ip6in4_entry_t), 0, sizeof(ip6in4_entry_t));
110   return ERR_OK;
111 }
112 
113 static void
ip6in4_entry_all_remove(void)114 ip6in4_entry_all_remove(void)
115 {
116   uint8_t i;
117   ip6in4_entry_t *entry = NULL;
118 
119   if (g_ip6in4_entry == NULL) {
120     LWIP_DEBUGF(IP6IN4_DEBUG, ("ip6in4 is not init\n"));
121     return;
122   }
123 
124   for (i = 0; i < g_ip6in4_entry_size; i++) {
125     entry = &g_ip6in4_entry[i];
126     if (entry->in_use != lwIP_TRUE) {
127       continue;
128     }
129 
130     (void)ip6in4_entry_remove(entry);
131   }
132 }
133 
134 static ip6in4_entry_t *
ip6in4_entry_new(void)135 ip6in4_entry_new(void)
136 {
137   uint32_t i;
138   ip6in4_entry_t *entry = NULL;
139 
140   if (g_ip6in4_entry == NULL) {
141     LWIP_DEBUGF(IP6IN4_DEBUG, ("ip6in4 is not init\n"));
142     return NULL;
143   }
144 
145   for (i = 0; i < g_ip6in4_entry_size; i++) {
146     entry = &g_ip6in4_entry[i];
147     if (entry->in_use == lwIP_TRUE) {
148       continue;
149     }
150 
151     if (g_ip6in4_entry_cnt < g_ip6in4_entry_size) {
152       g_ip6in4_entry_cnt++;
153     }
154 
155     entry->in_use = lwIP_TRUE;
156     return entry;
157   }
158 
159   return NULL;
160 }
161 
162 static err_t
ip6in4_entry_update(ip6in4_entry_t * entry,ip6_addr_t * ip6addr,ip4_addr_t * ip4addr,uint32_t lifetime)163 ip6in4_entry_update(ip6in4_entry_t *entry, ip6_addr_t *ip6addr, ip4_addr_t *ip4addr, uint32_t lifetime)
164 {
165   if ((entry == NULL) || (entry->in_use == lwIP_FALSE)) {
166     return ERR_ARG;
167   }
168 
169   if (ip6addr != NULL) {
170     entry->ip6 = *ip6addr;
171   }
172 
173   if (ip4addr != NULL) {
174     entry->ip4 = *ip4addr;
175   }
176 
177   if (lifetime > 0) {
178     entry->lifetime = lifetime;
179   }
180 
181   return ERR_OK;
182 }
183 
184 err_t
ip6in4_entry_add(ip6_addr_t * ip6addr,ip4_addr_t * ip4addr,uint32_t lifetime)185 ip6in4_entry_add(ip6_addr_t *ip6addr, ip4_addr_t *ip4addr, uint32_t lifetime)
186 {
187   err_t ret;
188   ip6in4_entry_t *entry = NULL;
189 
190   if ((ip6addr == NULL) || (ip4addr == NULL) || (lifetime == 0)) {
191     return ERR_ARG;
192   }
193 
194   entry = ip6in4_entry_new();
195   if (entry == NULL) {
196     return ERR_VAL;
197   }
198 
199   ret = ip6in4_entry_update(entry, ip6addr, ip4addr, lifetime);
200   if (ret != ERR_OK) {
201     (void)ip6in4_entry_remove(entry);
202     return ERR_VAL;
203   }
204 
205   return ERR_OK;
206 }
207 
208 static ip6in4_entry_t *
ip6in4_entry_find_by_ip6addr(const ip6_addr_t * ip6addr)209 ip6in4_entry_find_by_ip6addr(const ip6_addr_t *ip6addr)
210 {
211   uint32_t i;
212   ip6in4_entry_t *entry = NULL;
213 
214   if (ip6addr == NULL) {
215     return NULL;
216   }
217 
218   if (g_ip6in4_entry == NULL) {
219     LWIP_DEBUGF(IP6IN4_DEBUG, ("ip6in4 is not init\n"));
220     return NULL;
221   }
222 
223   for (i = 0; i < g_ip6in4_entry_size; i++) {
224     entry = &g_ip6in4_entry[i];
225     if (entry->in_use != lwIP_TRUE) {
226       continue;
227     }
228 
229     if (memcmp(ip6addr, &entry->ip6, sizeof(ip6_addr_t)) == 0) {
230       return entry;
231     }
232   }
233 
234   return NULL;
235 }
236 
237 static ip6in4_entry_t *
ip6in4_entry_find_by_ip4addr(const ip4_addr_t * ip4addr)238 ip6in4_entry_find_by_ip4addr(const ip4_addr_t *ip4addr)
239 {
240   uint32_t i;
241   ip6in4_entry_t *entry = NULL;
242 
243   if (ip4addr == NULL) {
244     return NULL;
245   }
246 
247   if (g_ip6in4_entry == NULL) {
248     LWIP_DEBUGF(IP6IN4_DEBUG, ("ip6in4 is not init\n"));
249     return NULL;
250   }
251 
252   for (i = 0; i < g_ip6in4_entry_size; i++) {
253     entry = &g_ip6in4_entry[i];
254     if (entry->in_use != lwIP_TRUE) {
255       continue;
256     }
257 
258     if (memcmp(ip4addr, &entry->ip4, sizeof(ip4_addr_t)) == 0) {
259       return entry;
260     }
261   }
262 
263   return NULL;
264 }
265 
266 static int
ip6in4_ip4_output(struct pbuf * p,struct ip6_hdr * ip6hdr,const ip6in4_entry_t * entry)267 ip6in4_ip4_output(struct pbuf *p, struct ip6_hdr *ip6hdr, const ip6in4_entry_t *entry)
268 {
269   err_t ret;
270 
271   p->ip6in4_ip6 = lwIP_TRUE;
272   LWIP_UNUSED_ARG(ip6hdr);
273   ret = ip4_output_if(p, NULL, &entry->ip4, IP_DEFAULT_TTL, 0, IP_PROTO_IP6IN4, g_ip6in4_nif);
274   if (ret != ERR_OK) {
275     LWIP_DEBUGF(IP6IN4_DEBUG, ("ip6in4_ip4_output: ip6in4 out fail\n"));
276   }
277   (void)pbuf_free(p);
278   return IP6IN4_PKT_HANDLED;
279 }
280 
281 static int
ip6in4_status_check()282 ip6in4_status_check()
283 {
284   if (g_ip6in4_inited == lwIP_FALSE) {
285     LWIP_DEBUGF(IP6IN4_DEBUG, ("ip6in4_status_check: ip6in4 is not init\n"));
286     return IP6IN4_RET_FAIL;
287   }
288   /* the node must be MBR */
289   if (lwip_rpl_is_br() == lwIP_FALSE) {
290     LWIP_DEBUGF(IP6IN4_DEBUG, ("ip6in4_status_check: not mbr node\n"));
291     return IP6IN4_RET_FAIL;
292   }
293   return IP6IN4_RET_OK;
294 }
295 
296 static int
ip6in4_ip6_packet_check(struct pbuf * p,const struct ip6_hdr * iphdr)297 ip6in4_ip6_packet_check(struct pbuf *p, const struct ip6_hdr *iphdr)
298 {
299   /* do not handle the linklocal/loopback/multicast packet */
300   if (ip6_addr_islinklocal(ip6_current_dest_addr()) ||
301       ip6_addr_isloopback(ip6_current_dest_addr()) ||
302       ip6_addr_ismulticast(ip6_current_dest_addr())) {
303     LWIP_DEBUGF(IP6IN4_DEBUG, ("ip6in4_ip6_input:pkt not handle\n"));
304     return IP6IN4_RET_FAIL;
305   }
306 
307   /* send ICMP6 if HL <= 1 */
308   if (IP6H_HOPLIM(iphdr) <= 1) {
309 #if LWIP_ICMP6
310     /* Don't send ICMP messages in response to ICMP messages */
311     if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
312       icmp6_time_exceeded(p, ICMP6_TE_HL);
313     }
314 #endif /* LWIP_ICMP6 */
315     LWIP_DEBUGF(IP6IN4_DEBUG, ("ip6in4_ip6_input:hop limit drop\n"));
316     IP6_STATS_INC(ip6.drop);
317     (void)pbuf_free(p);
318     return IP6IN4_RET_ERR;
319   }
320 
321   return IP6IN4_RET_OK;
322 }
323 
324 int
ip6in4_ip6_input(struct pbuf * p,struct ip6_hdr * iphdr,const struct netif * inp,const ip6_addr_t * tunnel_end)325 ip6in4_ip6_input(struct pbuf *p, struct ip6_hdr *iphdr, const struct netif *inp, const ip6_addr_t *tunnel_end)
326 {
327   int ret;
328   uint8_t rc;
329   ip6in4_entry_t *entry = NULL;
330   ip6_addr_t nhop = {0};
331   ip6_addr_t dest_addr;
332 
333   if ((p == NULL) || (iphdr == NULL) || (inp == NULL)) {
334     return IP6IN4_PKT_NOT_HANDLED;
335   }
336 
337   ret = ip6in4_status_check();
338   if (ret != IP6IN4_RET_OK) {
339     return IP6IN4_PKT_NOT_HANDLED;
340   }
341 
342   ret = ip6in4_ip6_packet_check(p, iphdr);
343   if (ret == IP6IN4_RET_FAIL) {
344     return IP6IN4_PKT_NOT_HANDLED;
345   } else if (ret == IP6IN4_RET_ERR) {
346     return IP6IN4_PKT_HANDLED;
347   }
348 
349   rc = lwip_rpl_is_rpl_netif(inp);
350   if (rc != lwIP_TRUE) {
351     return IP6IN4_PKT_NOT_HANDLED;
352   }
353 
354   /* now it is allowed to set the tunnel endpoint info outside of ip6in4. */
355   if (tunnel_end == NULL) {
356     ip6_addr_copy_from_packed(dest_addr, iphdr->dest);
357     ret = lwip_rpl_route_entry_nhop_get(&dest_addr, &nhop);
358     if (ret != ERR_OK) {
359       return IP6IN4_PKT_NOT_HANDLED;
360     }
361     tunnel_end = &nhop;
362   }
363 
364   entry = ip6in4_entry_find_by_ip6addr(tunnel_end);
365   if (entry == NULL) {
366     return IP6IN4_PKT_NOT_HANDLED;
367   }
368 
369   /* send the whole packet, using the ip4 */
370   return ip6in4_ip4_output(p, iphdr, entry);
371 }
372 
373 void
ip6in4_ip4_input(struct pbuf * p,struct netif * inp,const ip4_addr_t * src,const ip4_addr_t * dst)374 ip6in4_ip4_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *src, const ip4_addr_t *dst)
375 {
376   int ret;
377   ip6in4_entry_t *entry = NULL;
378   struct ip6_hdr *ip6hdr = NULL;
379 
380   if ((p == NULL) || (inp == NULL) || (src == NULL) || (dst == NULL)) {
381     if (p != NULL) {
382       (void)pbuf_free(p);
383     }
384     return;
385   }
386 
387   if (ip4_addr_ismulticast(dst) || ip4_addr_isbroadcast(dst, inp) ||
388       (inp != g_ip6in4_nif)) {
389     (void)pbuf_free(p);
390     return;
391   }
392 
393   ret = ip6in4_status_check();
394   if (ret != IP6IN4_RET_OK) {
395     (void)pbuf_free(p);
396     return;
397   }
398 
399   entry = ip6in4_entry_find_by_ip4addr(src);
400   if (entry == NULL) {
401     (void)pbuf_free(p);
402     return;
403   }
404 
405   if (p->len < IP6_HLEN) {
406     (void)pbuf_free(p);
407     return;
408   }
409 
410   ip6hdr = (struct ip6_hdr *)p->payload;
411   if (IP6H_V(ip6hdr) != IP6IN4_V6_VERSION) {
412     (void)pbuf_free(p);
413     return;
414   }
415 
416   /* it should check the route entry, when receive the ip6-in-ip4 packet.
417    * the ip6 may send the icmpv6 packet to the dest. */
418 #if defined(LWIP_IP6IN4_CHECK_IP6ADDR)
419   if (lwip_rpl_route_entry_lookup((ip6_addr_t *)&ip6hdr->dest) == NULL) {
420     (void)pbuf_free(p);
421     return;
422   }
423 #endif
424 
425   /* here just use ip6_input, if it need to handle the error message,
426    * the input function should be restructed, but it will take too much text size. */
427   (void)ip6_input(p, inp);
428 }
429 
430 err_t
ip6in4_entry_ip4_get(const ip6_addr_t * ip6,ip4_addr_t * ip4)431 ip6in4_entry_ip4_get(const ip6_addr_t *ip6, ip4_addr_t *ip4)
432 {
433   int ret;
434   ip6in4_entry_t *entry = NULL;
435   if ((ip6 == NULL) || (ip4 == NULL)) {
436     return ERR_ARG;
437   }
438 
439   ret = ip6in4_status_check();
440   if (ret != IP6IN4_RET_OK) {
441     return ERR_VAL;
442   }
443 
444   entry = ip6in4_entry_find_by_ip6addr(ip6);
445   if (entry == NULL) {
446     return ERR_VAL;
447   }
448 
449   *ip4 = entry->ip4;
450   return ERR_OK;
451 }
452 
453 #if LWIP_LOWPOWER
454 u32_t
ip6in4_tmr_tick(void)455 ip6in4_tmr_tick(void)
456 {
457   s16_t i;
458   u32_t tick = 0;
459   ip6in4_entry_t *entry = NULL;
460 
461   if ((g_ip6in4_inited != lwIP_TRUE) || (g_ip6in4_entry == NULL)) {
462     LOWPOWER_DEBUG(("%s tmr tick: 0\n", __func__));
463     return 0;
464   }
465 
466   for (i = 0; i < g_ip6in4_entry_size; i++) {
467     entry = &g_ip6in4_entry[i];
468     if (entry->in_use == lwIP_FALSE) {
469       continue;
470     }
471 
472     SET_TMR_TICK(tick, entry->lifetime);
473   }
474 
475   LOWPOWER_DEBUG(("%s tmr tick: %u\n", __func__, tick));
476   return tick;
477 }
478 #endif
479 
480 void
ip6in4_tmr(void)481 ip6in4_tmr(void)
482 {
483   uint32_t i;
484   ip6in4_entry_t *entry = NULL;
485 
486   if ((g_ip6in4_inited != lwIP_TRUE) || (g_ip6in4_entry == NULL)) {
487     LWIP_DEBUGF(IP6IN4_DEBUG, ("ip6in4 tmr: ip6in4 is not init\n"));
488     return;
489   }
490 
491   for (i = 0; i < g_ip6in4_entry_size; i++) {
492     entry = &g_ip6in4_entry[i];
493     if ((entry->in_use == lwIP_FALSE) || (entry->lifetime == LWIP_IP6IN4_LIFETIME_INFINITE)) {
494       continue;
495     }
496 
497     if (entry->lifetime <= (IP6IN4_TMR_INTERVAL / MS_PER_SECOND)) {
498       /* entry timeout, remove it. */
499       (void)ip6in4_entry_remove(entry);
500     } else {
501       entry->lifetime -= (IP6IN4_TMR_INTERVAL / MS_PER_SECOND);
502     }
503   }
504 }
505 
506 static err_t
ip6in4_entry_get(struct netif * nif,void * data)507 ip6in4_entry_get(struct netif *nif, void *data)
508 {
509   uint8_t i;
510   int rc;
511   const ip6_addr_t *ip6 = NULL;
512   lwip_ip6in4_entry_t *entry = (lwip_ip6in4_entry_t *)data;
513 
514   if ((g_ip6in4_inited != lwIP_TRUE) || (g_ip6in4_entry == NULL) ||
515       (g_ip6in4_nif == NULL)) {
516     LWIP_DEBUGF(IP6IN4_DEBUG, ("ip6in4 is not init\n"));
517     return ERR_VAL;
518   }
519 
520   if (!IP_IS_V4_VAL(g_ip6in4_nif->ip_addr) || (ip4_addr_isany(ip_2_ip4(&g_ip6in4_nif->ip_addr)) ||
521         (ip4_addr_isnone(ip_2_ip4(&g_ip6in4_nif->ip_addr))))) {
522     return ERR_VAL;
523   }
524 
525   entry->ip4 = ip_addr_get_ip4_u32(&g_ip6in4_nif->ip_addr);
526 
527   for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
528     ip6 = netif_ip6_addr(g_ip6in4_nif, i);
529     if (!ip6_addr_islinklocal(ip6)) {
530       continue;
531     }
532 
533     rc = memcpy_s(entry->ip6, sizeof(entry->ip6), ip6->addr, sizeof(ip6->addr));
534     if (rc != EOK) {
535       return ERR_VAL;
536     }
537 
538     break;
539   }
540 
541   if (i == LWIP_IPV6_NUM_ADDRESSES) {
542     return ERR_VAL;
543   }
544 
545 #ifndef LWIP_IP6IN4_LIFETIME_TIMER
546   entry->lifetime = LWIP_IP6IN4_LIFETIME_INFINITE;
547 #else
548   entry->lifetime = LWIP_IP6IN4_LIFETIME_DEFAULT;
549 #endif
550 
551   LWIP_UNUSED_ARG(nif);
552   return ERR_OK;
553 }
554 
555 int
lwip_ip6in4_entry_get(lwip_ip6in4_entry_t * entry)556 lwip_ip6in4_entry_get(lwip_ip6in4_entry_t *entry)
557 {
558   err_t ret;
559 
560   if (entry == NULL) {
561     return -1;
562   }
563 
564   ret = netifapi_call_argcb(ip6in4_entry_get, entry);
565   if (ret != ERR_OK) {
566     return -1;
567   }
568 
569   return 0;
570 }
571 
572 static err_t
ip6in4_entry_copy(const ip6in4_entry_t * ent,lwip_ip6in4_entry_t * entry)573 ip6in4_entry_copy(const ip6in4_entry_t *ent, lwip_ip6in4_entry_t *entry)
574 {
575   int ret;
576 
577   ret = memcpy_s(entry->ip6, sizeof(entry->ip6), ent->ip6.addr, sizeof(ent->ip6.addr));
578   if (ret != EOK) {
579     return ERR_VAL;
580   }
581 
582   entry->ip4 = ent->ip4.addr;
583   entry->lifetime = ent->lifetime;
584   return ERR_OK;
585 }
586 
587 static err_t
ip6in4_entry_all_get(struct netif * nif,void * data)588 ip6in4_entry_all_get(struct netif *nif, void *data)
589 {
590   err_t ret;
591   uint8_t i;
592   uint8_t j;
593   uint8_t cnt = 0;
594   lwip_ip6in4_entry_t *entry = NULL;
595   ip6in4_entry_t *ent = NULL;
596   ip6in4_entry_all_arg *arg = (ip6in4_entry_all_arg *)data;
597 
598   if ((g_ip6in4_inited != lwIP_TRUE) || (g_ip6in4_entry == NULL) ||
599       (g_ip6in4_nif == NULL)) {
600     LWIP_DEBUGF(IP6IN4_DEBUG, ("ip6in4 is not init\n"));
601     return ERR_VAL;
602   }
603   /* the first entry is the local config */
604   ret = ip6in4_entry_get(NULL, &arg->entry[0]);
605   if (ret != ERR_OK) {
606     return ERR_VAL;
607   }
608 
609   j = 0;
610   cnt++;
611   for (i = 1; i < arg->cnt; i++) {
612     entry = &arg->entry[i];
613     while (j < g_ip6in4_entry_size) {
614       if (g_ip6in4_entry[j].in_use == lwIP_TRUE) {
615         break;
616       }
617       j++;
618     }
619 
620     if (j == g_ip6in4_entry_size) {
621       break;
622     }
623 
624     ent = &g_ip6in4_entry[j];
625     ret = ip6in4_entry_copy(ent, entry);
626     if (ret != ERR_OK) {
627       return ERR_VAL;
628     }
629     cnt++;
630     j++;
631   }
632   LWIP_UNUSED_ARG(nif);
633   arg->ret_cnt = cnt;
634   return ERR_OK;
635 }
636 
637 int
lwip_ip6in4_entry_all_get(lwip_ip6in4_entry_t * entry,uint8_t cnt)638 lwip_ip6in4_entry_all_get(lwip_ip6in4_entry_t *entry, uint8_t cnt)
639 {
640   err_t ret;
641   ip6in4_entry_all_arg arg = {0};
642 
643   if ((entry == NULL) || (cnt == 0)) {
644     return -1;
645   }
646 
647   arg.entry = entry;
648   arg.cnt = cnt;
649 
650   ret = netifapi_call_argcb(ip6in4_entry_all_get, &arg);
651   if (ret != ERR_OK) {
652     return -1;
653   }
654 
655   return arg.ret_cnt;
656 }
657 
658 static err_t
ip6in4_entry_get_by_mac(struct netif * nif,void * data)659 ip6in4_entry_get_by_mac(struct netif *nif, void *data)
660 {
661   int rc;
662   err_t ret;
663   ip6in4_entry_t *ent = NULL;
664   ip6_addr_t ip6 = {0};
665   linklayer_addr_t mac = {0};
666   ip6in4_entry_mac_arg *arg = (ip6in4_entry_mac_arg *)data;
667 
668   if (g_ip6in4_inited != lwIP_TRUE) {
669     return ERR_VAL;
670   }
671 
672   rc = memcpy_s(mac.addr, sizeof(mac.addr), arg->mac, arg->len);
673   if (rc != EOK) {
674     return ERR_VAL;
675   }
676   mac.addrlen = arg->len;
677 
678   ret = netif_create_ip6_linklocal_address_from_mac(&mac, &ip6);
679   if (ret != ERR_OK) {
680     return ERR_VAL;
681   }
682 
683   ent = ip6in4_entry_find_by_ip6addr(&ip6);
684   if (ent == NULL) {
685     return ERR_VAL;
686   }
687 
688   ret = ip6in4_entry_copy(ent, arg->entry);
689   if (ret != ERR_OK) {
690     return ERR_VAL;
691   }
692 
693   LWIP_UNUSED_ARG(nif);
694   return ERR_OK;
695 }
696 
697 int
lwip_ip6in4_entry_get_by_mac(const char * mac,uint8_t len,lwip_ip6in4_entry_t * entry)698 lwip_ip6in4_entry_get_by_mac(const char *mac, uint8_t len, lwip_ip6in4_entry_t *entry)
699 {
700   err_t ret;
701   ip6in4_entry_mac_arg arg = {0};
702 
703   if ((entry == NULL) || (mac == NULL) || (len != LWIP_IP6IN4_MAC_LEN)) {
704     return -1;
705   }
706 
707   arg.entry = entry;
708   arg.mac = mac;
709   arg.len = len;
710 
711   ret = netifapi_call_argcb(ip6in4_entry_get_by_mac, &arg);
712   if (ret != ERR_OK) {
713     return -1;
714   }
715 
716   return 0;
717 }
718 
719 ip6in4_entry_t *
ip6in4_entry_get_next_inuse(uint32_t * state)720 ip6in4_entry_get_next_inuse(uint32_t *state)
721 {
722   uint32_t i;
723   ip6in4_entry_t *entry = NULL;
724 
725   if (state == NULL) {
726     return NULL;
727   }
728 
729   if ((g_ip6in4_inited != lwIP_TRUE) || (g_ip6in4_entry == NULL) ||
730       (g_ip6in4_nif == NULL)) {
731     LWIP_DEBUGF(IP6IN4_DEBUG, ("ip6in4 is not init\n"));
732     return NULL;
733   }
734 
735   for (i = *state; i < g_ip6in4_entry_size; i++) {
736     entry = &g_ip6in4_entry[i];
737     if (entry->in_use != lwIP_TRUE) {
738       continue;
739     }
740 
741     *state = i + 1;
742     return entry;
743   }
744 
745   return NULL;
746 }
747 
748 static err_t
ip6in4_entry_sync(const lwip_ip6in4_entry_t * entry,uint8_t cnt)749 ip6in4_entry_sync(const lwip_ip6in4_entry_t *entry, uint8_t cnt)
750 {
751   uint8_t i;
752   int rc;
753   err_t ret;
754   ip6_addr_t ip6;
755   ip4_addr_t ip4;
756   const ip6_addr_t *linklocal = NULL;
757   const lwip_ip6in4_entry_t *ent = NULL;
758 
759   for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
760     linklocal = netif_ip6_addr(g_ip6in4_nif, i);
761     if (ip6_addr_islinklocal(linklocal)) {
762       break;
763     }
764   }
765 
766   if (i == LWIP_IPV6_NUM_ADDRESSES) {
767     return ERR_VAL;
768   }
769 
770   ip6in4_entry_all_remove();
771 
772   for (i = 0; i < cnt; i++) {
773     ent = &entry[i];
774     /* filter the local entry */
775     if (memcmp(ent->ip6, linklocal->addr, sizeof(linklocal->addr)) == 0) {
776       continue;
777     }
778 
779     (void)memset_s(&ip6, sizeof(ip6), 0, sizeof(ip6));
780     rc = memcpy_s(ip6.addr, sizeof(ip6.addr), ent->ip6, sizeof(ent->ip6));
781     if (rc != EOK) {
782       return ERR_VAL;
783     }
784 
785     ip4.addr = ent->ip4;
786     ret = ip6in4_entry_add(&ip6, &ip4, ent->lifetime);
787     if (ret != ERR_OK) {
788       return ERR_VAL;
789     }
790   }
791 
792   return ERR_OK;
793 }
794 
795 static err_t
ip6in4_entry_add_update(const lwip_ip6in4_entry_t * entry,uint8_t cnt)796 ip6in4_entry_add_update(const lwip_ip6in4_entry_t *entry, uint8_t cnt)
797 {
798   uint8_t i;
799   int rc;
800   err_t ret;
801   ip6_addr_t ip6;
802   ip4_addr_t ip4;
803   ip6in4_entry_t *entry64 = NULL;
804   const lwip_ip6in4_entry_t *ent = NULL;
805   const ip6_addr_t *linklocal = NULL;
806 
807   for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
808     linklocal = netif_ip6_addr(g_ip6in4_nif, i);
809     if (ip6_addr_islinklocal(linklocal)) {
810       break;
811     }
812   }
813 
814   if (i == LWIP_IPV6_NUM_ADDRESSES) {
815     return ERR_VAL;
816   }
817 
818   for (i = 0; i < cnt; i++) {
819     ent = &entry[i];
820     /* filter the local entry */
821     if (memcmp(ent->ip6, linklocal->addr, sizeof(linklocal->addr)) == 0) {
822       continue;
823     }
824 
825     (void)memset_s(&ip6, sizeof(ip6), 0, sizeof(ip6));
826     rc = memcpy_s(ip6.addr, sizeof(ip6.addr), ent->ip6, sizeof(ent->ip6));
827     if (rc != EOK) {
828       return ERR_VAL;
829     }
830 
831     ip4.addr = ent->ip4;
832     entry64 = ip6in4_entry_find_by_ip6addr(&ip6);
833     if (entry64 == NULL) {
834       ret = ip6in4_entry_add(&ip6, &ip4, ent->lifetime);
835       if (ret != ERR_OK) {
836         return ERR_VAL;
837       }
838       continue;
839     }
840 
841     ret = ip6in4_entry_update(entry64, NULL, &ip4, ent->lifetime);
842     if (ret != ERR_OK) {
843       return ERR_VAL;
844     }
845   }
846 
847   return ERR_OK;
848 }
849 
850 static err_t
ip6in4_entry_delete(const lwip_ip6in4_entry_t * entry,uint8_t cnt)851 ip6in4_entry_delete(const lwip_ip6in4_entry_t *entry, uint8_t cnt)
852 {
853   uint8_t i;
854   int rc;
855   err_t ret;
856   ip6_addr_t ip6;
857   ip6in4_entry_t *entry64 = NULL;
858   const lwip_ip6in4_entry_t *ent = NULL;
859 
860   for (i = 0; i < cnt; i++) {
861     ent = &entry[i];
862     (void)memset_s(&ip6, sizeof(ip6), 0, sizeof(ip6));
863     rc = memcpy_s(ip6.addr, sizeof(ip6.addr), ent->ip6, sizeof(ent->ip6));
864     if (rc != EOK) {
865       return ERR_VAL;
866     }
867 
868     entry64 = ip6in4_entry_find_by_ip6addr(&ip6);
869     if (entry64 == NULL) {
870       continue;
871     }
872 
873     ret = ip6in4_entry_remove(entry64);
874     if (ret != ERR_OK) {
875       return ERR_VAL;
876     }
877   }
878 
879   return ERR_OK;
880 }
881 
882 static err_t
ip6in4_entry_set(struct netif * nif,void * data)883 ip6in4_entry_set(struct netif *nif, void *data)
884 {
885   ip6in4_entry_update_arg *arg = (ip6in4_entry_update_arg *)data;
886 
887   if ((g_ip6in4_inited != lwIP_TRUE) || (g_ip6in4_entry == NULL) ||
888       (g_ip6in4_nif == NULL)) {
889     LWIP_DEBUGF(IP6IN4_DEBUG, ("ip6in4 is not init\n"));
890     return ERR_VAL;
891   }
892 
893   if (arg->evt == LWIP_IP6IN4_ENTRY_SYNC) {
894     return ip6in4_entry_sync(arg->entry, arg->cnt);
895   }
896 
897   if (arg->evt == LWIP_IP6IN4_ENTRY_ADD_UPDATE) {
898     return ip6in4_entry_add_update(arg->entry, arg->cnt);
899   }
900 
901   if (arg->evt == LWIP_IP6IN4_ENTRY_DELETE) {
902     return ip6in4_entry_delete(arg->entry, arg->cnt);
903   }
904   LWIP_UNUSED_ARG(nif);
905   return ERR_ARG;
906 }
907 
908 static int
lwip_ip6in4_entry_set(const lwip_ip6in4_entry_t * entry,uint8_t cnt,uint8_t evt)909 lwip_ip6in4_entry_set(const lwip_ip6in4_entry_t *entry, uint8_t cnt, uint8_t evt)
910 {
911   err_t ret;
912   ip6in4_entry_update_arg arg;
913 
914   if ((entry == NULL) || (cnt == 0)) {
915     return -1;
916   }
917 
918   (void)memset_s(&arg, sizeof(arg), 0, sizeof(arg));
919   arg.entry = entry;
920   arg.cnt = cnt;
921   arg.evt = evt;
922 
923   ret = netifapi_call_argcb(ip6in4_entry_set, &arg);
924   if (ret != ERR_OK) {
925     return -1;
926   }
927 
928   return 0;
929 }
930 
931 int
lwip_ip6in4_entry_add_update(const lwip_ip6in4_entry_t * entry,uint8_t cnt)932 lwip_ip6in4_entry_add_update(const lwip_ip6in4_entry_t *entry, uint8_t cnt)
933 {
934   return lwip_ip6in4_entry_set(entry, cnt, LWIP_IP6IN4_ENTRY_ADD_UPDATE);
935 }
936 
937 int
lwip_ip6in4_entry_delete(const lwip_ip6in4_entry_t * entry,uint8_t cnt)938 lwip_ip6in4_entry_delete(const lwip_ip6in4_entry_t *entry, uint8_t cnt)
939 {
940   return lwip_ip6in4_entry_set(entry, cnt, LWIP_IP6IN4_ENTRY_DELETE);
941 }
942 
943 int
lwip_ip6in4_entry_sync(const lwip_ip6in4_entry_t * entry,uint8_t cnt)944 lwip_ip6in4_entry_sync(const lwip_ip6in4_entry_t *entry, uint8_t cnt)
945 {
946   return lwip_ip6in4_entry_set(entry, cnt, LWIP_IP6IN4_ENTRY_SYNC);
947 }
948 
949 err_t
ip6in4_init(struct netif * inp,uint8_t mbr_cnt)950 ip6in4_init(struct netif *inp, uint8_t mbr_cnt)
951 {
952   size_t entry_size;
953 
954   if ((inp == NULL) || (mbr_cnt == 0)) {
955     return ERR_ARG;
956   }
957 
958   if (g_ip6in4_inited == lwIP_TRUE) {
959     return ERR_OK;
960   }
961 
962   entry_size = mbr_cnt * sizeof(ip6in4_entry_t);
963   g_ip6in4_entry = (ip6in4_entry_t *)mem_malloc(entry_size);
964   if (g_ip6in4_entry == NULL) {
965     return ERR_MEM;
966   }
967   g_ip6in4_entry_size = mbr_cnt;
968   g_ip6in4_entry_cnt = 0;
969   (void)memset_s(g_ip6in4_entry, entry_size, 0, entry_size);
970   g_ip6in4_nif = inp;
971   g_ip6in4_inited = lwIP_TRUE;
972   return ERR_OK;
973 }
974 
975 err_t
ip6in4_deinit(void)976 ip6in4_deinit(void)
977 {
978   if (g_ip6in4_inited == lwIP_FALSE) {
979     return ERR_OK;
980   }
981 
982   if (g_ip6in4_entry != NULL) {
983     mem_free(g_ip6in4_entry);
984     g_ip6in4_entry_cnt = 0;
985     g_ip6in4_entry = NULL;
986   }
987   g_ip6in4_entry_size = 0;
988   g_ip6in4_nif = NULL;
989   g_ip6in4_inited = lwIP_FALSE;
990   return ERR_OK;
991 }
992 
993 err_t
ip6in4_deinit_netif(const struct netif * ntf)994 ip6in4_deinit_netif(const struct netif *ntf)
995 {
996   if ((ntf == NULL) || (g_ip6in4_inited == lwIP_FALSE) || (ntf != g_ip6in4_nif)) {
997     return ERR_ARG;
998   }
999 
1000   return ip6in4_deinit();
1001 }
1002 
1003 static err_t
ip6in4_init_with_name(struct netif * nif,void * data)1004 ip6in4_init_with_name(struct netif *nif, void *data)
1005 {
1006   ip6in4_init_arg *arg = (ip6in4_init_arg *)data;
1007   nif = netif_find(arg->name);
1008   if (nif == NULL) {
1009     return ERR_ARG;
1010   }
1011 
1012   return ip6in4_init(nif, arg->mbr_cnt);
1013 }
1014 
1015 int
lwip_ip6in4_init(const char * name,uint8_t len,uint8_t mbr_cnt)1016 lwip_ip6in4_init(const char *name, uint8_t len, uint8_t mbr_cnt)
1017 {
1018   err_t ret;
1019   ip6in4_init_arg arg = {0};
1020 
1021   if ((name == NULL) || (len >= NETIF_NAMESIZE) || (len < IP6IN4_NETIF_NAME_LEN_MIN) || (mbr_cnt == 0)) {
1022     return -1;
1023   }
1024 
1025   arg.name = name;
1026   arg.len = len;
1027   arg.mbr_cnt = mbr_cnt;
1028 
1029   ret = netifapi_call_argcb(ip6in4_init_with_name, &arg);
1030   if (ret != ERR_OK) {
1031     return -1;
1032   }
1033 
1034   return 0;
1035 }
1036 
1037 static err_t
ip6in4_exit(struct netif * nif)1038 ip6in4_exit(struct netif *nif)
1039 {
1040   LWIP_UNUSED_ARG(nif);
1041   return ip6in4_deinit();
1042 }
1043 
1044 int
lwip_ip6in4_deinit(void)1045 lwip_ip6in4_deinit(void)
1046 {
1047   err_t ret;
1048   ret = netifapi_netif_common(NULL, NULL, ip6in4_exit);
1049   if (ret != ERR_OK) {
1050     return -1;
1051   }
1052 
1053   return 0;
1054 }
1055 
1056 #endif /* LWIP_IP6IN4 */
1057