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