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 NAT64 dhcp proxy
15 * Author: NA
16 * Create: 2019
17 */
18 #include "lwip/opt.h"
19 #include "lwip/dhcp.h"
20 #if LWIP_NAT64
21 #include "arch/sys_arch.h"
22 #include "lwip/nat64.h"
23 #include "lwip/nat64_addr.h"
24 #include "lwip/nat64_v4_dhcpc.h"
25 #include "lwip/lwip_rpl.h"
26 #include "rpl_event_api.h"
27
28 err_t
nat64_dhcp_request_ip(struct netif * ntf,const linklayer_addr_t * lladdr,const ip4_addr_t * ip)29 nat64_dhcp_request_ip(struct netif *ntf, const linklayer_addr_t *lladdr, const ip4_addr_t *ip)
30 {
31 err_t ret;
32 #if LWIP_DHCP_SUBSTITUTE
33 dhcp_num_t index = 0;
34 #endif
35 if ((ntf == NULL) || (lladdr == NULL)) {
36 return ERR_ARG;
37 }
38
39 #if LWIP_DHCP_SUBSTITUTE
40 ret = nat64_entry_mac_to_idx(lladdr->addr, lladdr->addrlen, &index);
41 if (ret != ERR_OK) {
42 return ERR_VAL;
43 }
44
45 ret = dhcp_substitute_start(ntf, index, ip->addr);
46 #else
47 ret = ERR_ARG;
48 #endif
49
50 return ret;
51 }
52
53 err_t
nat64_dhcp_stop(struct netif * ntf,const linklayer_addr_t * lladdr,u8_t now)54 nat64_dhcp_stop(struct netif *ntf, const linklayer_addr_t *lladdr, u8_t now)
55 {
56 err_t ret;
57 #if LWIP_DHCP_SUBSTITUTE
58 dhcp_num_t index = 0;
59 #endif
60 if ((ntf == NULL) || (lladdr == NULL)) {
61 return ERR_ARG;
62 }
63 #if LWIP_DHCP_SUBSTITUTE
64 ret = nat64_entry_mac_to_idx(lladdr->addr, lladdr->addrlen, &index);
65 if (ret != ERR_OK) {
66 return ERR_VAL;
67 }
68
69 dhcp_substitute_stop(ntf, index, now);
70 ret = ERR_OK;
71 #else
72 ret = ERR_ARG;
73 #endif
74
75 return ret;
76 }
77
78
79 void
nat64_dhcp_ip4_event(const u8_t * mac,u8_t maclen,const ip4_addr_t * ipaddr,int event)80 nat64_dhcp_ip4_event(const u8_t *mac, u8_t maclen, const ip4_addr_t *ipaddr, int event)
81 {
82 nat64_entry_t *entry = NULL;
83 int ret;
84 linklayer_addr_t llmac;
85 if (mac == NULL) {
86 return;
87 }
88
89 (void)memset_s(&llmac, sizeof(linklayer_addr_t), 0, sizeof(linklayer_addr_t));
90 ret = memcpy_s(llmac.addr, sizeof(llmac.addr), mac, maclen);
91 if (ret != EOK) {
92 LWIP_DEBUGF(NAT64_DEBUG, ("%s:memcpy_s fail(%d)\n", __FUNCTION__, ret));
93 return;
94 }
95 llmac.addrlen = maclen > sizeof(llmac.addr) ? sizeof(llmac.addr) : maclen;
96 entry = nat64_entry_lookup_by_mac(&llmac);
97 if ((entry == NULL) || (entry->nat64_sync == lwIP_TRUE)) {
98 return;
99 }
100
101 if (((event == NAT64_DHCP_EVENT_OFFER) || (event == NAT64_DHCP_EVENT_RENEW)) &&
102 (ipaddr != NULL)) {
103 if ((entry->state == NAT64_STATE_DHCP_REQUEST) ||
104 (entry->state == NAT64_STATE_ESTABLISH)) {
105 entry->state = NAT64_STATE_ESTABLISH;
106 #if !LWIP_NAT64_MIN_SUBSTITUTE
107 /* dhcp clinet renew its ip, get ipv4 addr may change */
108 if (ip4_addr_isany_val(entry->ip)) {
109 ip4_addr_copy(entry->ip, *ipaddr);
110 #if LWIP_MMBR && LWIP_NAT64_CHANGE_MSG
111 nat64_send_change_entry_msg(entry, RPL_EVT_NODE_NAT64_ADD);
112 #endif /* LWIP_MMBR && LWIP_NAT64_CHANGE_MSG */
113 } else if (!ip4_addr_cmp(ipaddr, &entry->ip)) {
114 ip4_addr_copy(entry->ip, *ipaddr);
115 #if LWIP_MMBR && LWIP_NAT64_CHANGE_MSG
116 nat64_send_change_entry_msg(entry, RPL_EVT_NODE_NAT64_UPDATE);
117 } else {
118 /*
119 * When a node switches from an MBR to another MBR and gets the dhcp event,
120 * it also needs to send the add event because the IPv4 address of the node remains unchanged.
121 */
122 nat64_send_change_entry_msg(entry, RPL_EVT_NODE_NAT64_ADD);
123 #endif /* LWIP_MMBR && LWIP_NAT64_CHANGE_MSG */
124 }
125 ip6_addr_t ip6addr;
126 if (nat64_entry_to6(entry, &ip6addr) == 0) {
127 lwip_notify_rpl_get_ipv4_addr(entry->mnid, &ip6addr);
128 }
129 #else
130 (void)ipaddr;
131 #endif
132 return;
133 }
134 }
135
136 if (event == NAT64_DHCP_EVENT_RELEASE) {
137 entry->state = NAT64_STATE_DIRECT_RELEASE;
138 entry->lifetime = 0;
139 }
140 }
141 #endif
142