• 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: according the rfc 6052, the prefix length could be 32/40/48/56/64/96.
15  * but only 96 prefix length can be supported in our nat64 now.
16  * when the rpl start, the prefix will be setted, now this prefix is used in nat64.
17  * noted:this prefix should be stored independently in nat64 when needed.
18  * Author: NA
19  * Create: 2019
20  */
21 #include "lwip/opt.h"
22 #include "lwip/dhcp.h"
23 #if LWIP_NAT64
24 #include "lwip/pbuf.h"
25 #include "lwip/netif.h"
26 #include "lwip/ip.h"
27 #include "lwip/nat64.h"
28 #include "lwip/lwip_rpl.h"
29 #include "lwip/nat64_addr.h"
30 #include "lwip/nat64_dns64.h"
31 
32 /* maybe the prefix can be stored */
33 int
nat64_stateless_addr_4to6(const ip4_addr_t * ip4addr,ip6_addr_t * ip6addr)34 nat64_stateless_addr_4to6(const ip4_addr_t *ip4addr, ip6_addr_t *ip6addr)
35 {
36   ip6_addr_t prefix;
37   uint8_t len;
38   err_t err;
39 
40   if ((ip4addr == NULL) || (ip6addr == NULL)) {
41     return -1;
42   }
43   (void)memset_s(&prefix, sizeof(ip6_addr_t), 0, sizeof(ip6_addr_t));
44 #ifdef NAT64_USING_DAG_PREFIX
45   err = lwip_rpl_get_default_prefix(&prefix, &len);
46 #elif LWIP_DNS64
47   err = nat64_dns64_get_prefix(&prefix, &len);
48 #else
49   err = ERR_VAL;
50 #endif
51   if (err != ERR_OK) {
52     return -1;
53   }
54 
55   (void)len;
56   /* the address convert should be related with the prefix len, here is for simple */
57   ip6_addr_copy_ptr(ip6addr, &prefix);
58   /* the last 32bit address of ipv6 is ipv4 address. */
59   ip6addr->addr[3] = ip4addr->addr;
60 
61   return 0;
62 }
63 
64 /* handle special prefix or different prefix length */
65 int
nat64_stateless_addr_6to4(const ip6_addr_t * ip6addr,ip4_addr_t * ip4addr)66 nat64_stateless_addr_6to4(const ip6_addr_t *ip6addr, ip4_addr_t *ip4addr)
67 {
68   ip6_addr_t prefix;
69   err_t err;
70 
71   if ((ip4addr == NULL) || (ip6addr == NULL)) {
72     return -1;
73   }
74 
75   if (nat64_addr_is_ip4(ip6addr) == 0) {
76     return -1;
77   }
78    /* the last 32bit address of ipv6 */
79   ip4addr->addr = ip6addr->addr[3];
80   (void)memset_s(&prefix, sizeof(ip6_addr_t), 0, sizeof(ip6_addr_t));
81 #ifdef LWIP_NAT64_SAME_PREFIX
82   uint8_t len;
83   err = lwip_rpl_get_default_prefix(&prefix, &len);
84   if (err != ERR_OK) {
85     return -1;
86   }
87 
88   /* 96 prefix length is used now, should check that (96 - prefix.length) bit is zero */
89   if (memcmp(ip6addr, &prefix, len >> 3) == 0) {
90     ip4addr->addr = ip6addr->addr[3]; /* the last address of ipv6 */
91     return 0;
92   }
93 
94   return -1;
95 #else
96   err = 0;
97   (void)err;
98   (void)prefix;
99   return 0;
100 #endif
101 }
102 
103 int
nat64_entry_to6(const nat64_entry_t * entry,ip6_addr_t * ip6addr)104 nat64_entry_to6(const nat64_entry_t *entry, ip6_addr_t *ip6addr)
105 {
106   ip6_addr_t prefix;
107   uint8_t len;
108   err_t err;
109 
110   if ((entry == NULL) || (ip6addr == NULL)) {
111     return -1;
112   }
113   (void)memset_s(&prefix, sizeof(ip6_addr_t), 0, sizeof(ip6_addr_t));
114   err = lwip_rpl_get_default_prefix(&prefix, &len);
115   if (err != ERR_OK) {
116     return -1;
117   }
118 
119   (void)len;
120   ip6_addr_copy_ptr(ip6addr, &prefix);
121   lwip_rpl_set_ip6_iid(&entry->mac, entry->orig_mnid, ip6addr);
122 
123   return 0;
124 }
125 
126 int
nat64_entry_to4(const nat64_entry_t * entry,ip4_addr_t * ip4addr)127 nat64_entry_to4(const nat64_entry_t *entry, ip4_addr_t *ip4addr)
128 {
129 #if LWIP_NAT64_MIN_SUBSTITUTE
130   dhcp_num_t index = 0;
131   ip4_addr_t ip;
132   err_t ret;
133 #endif
134 
135 #if LWIP_NAT64_MIN_SUBSTITUTE
136   ret = nat64_entry_mac_to_idx(entry->mac.addr, entry->mac.addrlen, &index);
137   if (ret != ERR_OK) {
138     return -1;
139   }
140   (void)memset_s(&ip, sizeof(ip4_addr_t), 0, sizeof(ip4_addr_t));
141 #endif
142 
143   if ((entry->state == NAT64_STATE_ESTABLISH) &&
144 #if !LWIP_NAT64_MIN_SUBSTITUTE
145       (!ip4_addr_isany_val(entry->ip))
146 #elif LWIP_DHCP_SUBSTITUTE
147       (dhcp_substitute_idx_to_ip(nat64_netif_get(), index, &ip) == ERR_OK) &&
148       (!ip4_addr_isany_val(ip))
149 #else
150       (lwIP_FALSE)
151 #endif
152      ) {
153 #if !LWIP_NAT64_MIN_SUBSTITUTE
154     ip4_addr_copy(*ip4addr, entry->ip);
155 #elif LWIP_DHCP_SUBSTITUTE
156     ip4_addr_copy(*ip4addr, ip);
157 #else
158     ip4addr->addr = 0;
159 #endif
160     return 0;
161   }
162 
163   return -1;
164 }
165 
166 int
nat64_addr_6to4(const ip6_addr_t * ip6addr,ip4_addr_t * ip4addr)167 nat64_addr_6to4(const ip6_addr_t *ip6addr, ip4_addr_t *ip4addr)
168 {
169   linklayer_addr_t lladdr;
170   nat64_entry_t *entry = NULL;
171   int ret;
172 
173   if ((ip4addr == NULL) || (ip6addr == NULL)) {
174     return -1;
175   }
176   /* 64ff:9b/96 prefix is unique */
177   ret = nat64_stateless_addr_6to4(ip6addr, ip4addr);
178   if (ret == 0) {
179     return 0;
180   }
181 
182   ret = lwip_rpl_get_lladdr(ip6addr, &lladdr);
183   if (ret != ERR_OK) {
184     return -1;
185   }
186 
187   entry = nat64_entry_lookup_by_mac(&lladdr);
188   if (entry == NULL) {
189     return -1;
190   }
191 
192   return nat64_entry_to4(entry, ip4addr);
193 }
194 
195 int
nat64_addr_is_ip4(const ip6_addr_t * ip6addr)196 nat64_addr_is_ip4(const ip6_addr_t *ip6addr)
197 {
198   ip6_addr_t prefix;
199   uint8_t len;
200   err_t err;
201 
202   if (ip6addr == NULL) {
203     return 0;
204   }
205   (void)memset_s(&prefix, sizeof(ip6_addr_t), 0, sizeof(ip6_addr_t));
206 #ifdef NAT64_USING_DAG_PREFIX
207   err = lwip_rpl_get_default_prefix(&prefix, &len);
208 #elif LWIP_DNS64
209   err = nat64_dns64_get_prefix(&prefix, &len);
210 #else
211   err = ERR_VAL;
212 #endif
213   if (err != ERR_OK) {
214     return 0;
215   }
216   /* bit64~71 is not zero, the address is not ipv4 */
217   if (memcmp(&prefix, ip6addr, len >> 3) != 0) {
218     return 0;
219   }
220 
221   return 1;
222 }
223 
224 #endif
225