]>
Commit | Line | Data |
---|---|---|
4231f419 MT |
1 | #!/bin/bash |
2 | ############################################################################### | |
3 | # # | |
4 | # IPFire.org - A linux based firewall # | |
5 | # Copyright (C) 2010 Michael Tremer & Christian Schmidt # | |
6 | # # | |
7 | # This program is free software: you can redistribute it and/or modify # | |
8 | # it under the terms of the GNU General Public License as published by # | |
9 | # the Free Software Foundation, either version 3 of the License, or # | |
10 | # (at your option) any later version. # | |
11 | # # | |
12 | # This program is distributed in the hope that it will be useful, # | |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
15 | # GNU General Public License for more details. # | |
16 | # # | |
17 | # You should have received a copy of the GNU General Public License # | |
18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
19 | # # | |
20 | ############################################################################### | |
21 | ||
e617226b MT |
22 | IP_SUPPORTED_PROTOCOLS="${IP_SUPPORTED_PROTOCOLS} ipv6" |
23 | ||
4231f419 | 24 | function ipv6_device_autoconf_enable() { |
9f742d49 MT |
25 | local device="${1}" |
26 | assert device_exists "${device}" | |
4231f419 | 27 | |
9f742d49 MT |
28 | sysctl_set "net.ipv6.conf.${device}.accept_ra" 1 |
29 | sysctl_set "net.ipv6.conf.${device}.autoconf" 1 | |
4231f419 MT |
30 | } |
31 | ||
32 | function ipv6_device_autoconf_disable() { | |
9f742d49 MT |
33 | local device="${1}" |
34 | assert device_exists "${device}" | |
58fb41ee | 35 | |
9f742d49 MT |
36 | sysctl_set "net.ipv6.conf.${device}.accept_ra" 0 |
37 | sysctl_set "net.ipv6.conf.${device}.autoconf" 0 | |
58fb41ee MT |
38 | } |
39 | ||
40 | # Enable IPv6 RFC3041 privacy extensions if desired | |
41 | function ipv6_device_privacy_extensions_enable() { | |
9f742d49 MT |
42 | local device="${1}" |
43 | assert device_exists "${device}" | |
58fb41ee | 44 | |
9f742d49 | 45 | sysctl_set "net.ipv6.conf.${device}.use_tempaddr" 2 |
58fb41ee MT |
46 | } |
47 | ||
48 | function ipv6_device_privacy_extensions_disable() { | |
9f742d49 MT |
49 | local device="${1}" |
50 | assert device_exists "${device}" | |
58fb41ee | 51 | |
9f742d49 | 52 | sysctl_set "net.ipv6.conf.${device}.use_tempaddr" 0 |
4231f419 MT |
53 | } |
54 | ||
55 | function ipv6_is_valid() { | |
fa6df98c | 56 | ipcalc --ipv6 -c $@ >/dev/null 2>&1 |
58fb41ee | 57 | |
fa6df98c MT |
58 | case "$?" in |
59 | 0) | |
60 | return ${EXIT_OK} | |
61 | ;; | |
62 | *) | |
38f61548 | 63 | return ${EXIT_ERROR} |
fa6df98c MT |
64 | ;; |
65 | esac | |
4231f419 MT |
66 | } |
67 | ||
cb965348 MT |
68 | function ipv6_prefix_is_valid() { |
69 | local prefix=${1} | |
70 | assert isset prefix | |
71 | ||
72 | [ ${prefix} -le 0 ] && return ${EXIT_FALSE} | |
73 | [ ${prefix} -gt 128 ] && return ${EXIT_FALSE} | |
74 | ||
75 | return ${EXIT_TRUE} | |
76 | } | |
77 | ||
ea878018 MT |
78 | ipv6_prefix_size_is_valid_for_delegation() { |
79 | local prefix_size="${1}" | |
80 | assert isinteger prefix_size | |
81 | ||
82 | # For prefix delegation, the prefix must be between /48 and /64 | |
83 | # (RFC3769, section 3.1) | |
84 | [[ ${prefix_size} -lt 48 ]] && return ${EXIT_FALSE} | |
85 | [[ ${prefix_size} -gt 64 ]] && return ${EXIT_FALSE} | |
86 | ||
87 | return ${EXIT_TRUE} | |
88 | } | |
89 | ||
9390b61b SS |
90 | function ipv6_get_prefix() { |
91 | ip_get_prefix "$@" | |
92 | } | |
93 | ||
94 | function ipv6_split_prefix() { | |
95 | ip_split_prefix "$@" | |
96 | } | |
97 | ||
4231f419 MT |
98 | function ipv6_implode() { |
99 | local address=${1} | |
58fb41ee MT |
100 | assert isset address |
101 | ||
ab70371d MT |
102 | local ADDRESS6_IMPL |
103 | eval $(ipcalc -6 -i ${address} 2>/dev/null) | |
104 | assert isset ADDRESS6_IMPL | |
4231f419 | 105 | |
ab70371d | 106 | print "${ADDRESS6_IMPL}" |
4231f419 MT |
107 | } |
108 | ||
109 | function ipv6_explode() { | |
110 | local address=${1} | |
58fb41ee MT |
111 | assert isset address |
112 | ||
ab70371d | 113 | # Nothing to do if the length of the address is 39. |
4231f419 | 114 | if [ ${#address} -eq 39 ]; then |
ab70371d MT |
115 | print "${address}" |
116 | return ${EXIT_OK} | |
4231f419 MT |
117 | fi |
118 | ||
ab70371d MT |
119 | local ADDRESS6_EXPL |
120 | eval $(ipcalc -6 -e ${address} 2>/dev/null) | |
121 | assert isset ADDRESS6_EXPL | |
4231f419 | 122 | |
ab70371d MT |
123 | print "${ADDRESS6_EXPL}" |
124 | } | |
4231f419 | 125 | |
ab70371d MT |
126 | function ipv6_addr_eq() { |
127 | local addr1=${1} | |
128 | assert isset addr1 | |
4231f419 | 129 | |
ab70371d MT |
130 | local addr2=${2} |
131 | assert isset addr2 | |
4231f419 | 132 | |
ab70371d MT |
133 | local addr |
134 | for addr in addr1 addr2; do | |
135 | printf -v ${addr} "%s" $(ipv6_explode ${!addr}) | |
136 | done | |
4231f419 | 137 | |
ab70371d MT |
138 | [[ "${addr1}" = "${addr2}" ]] \ |
139 | && return ${EXIT_TRUE} || return ${EXIT_FALSE} | |
140 | } | |
4231f419 | 141 | |
ab70371d MT |
142 | function ipv6_addr_gt() { |
143 | local addr1=${1} | |
144 | assert isset addr1 | |
4231f419 | 145 | |
ab70371d MT |
146 | local addr2=${2} |
147 | assert isset addr2 | |
4231f419 | 148 | |
ab70371d MT |
149 | local addr |
150 | for addr in addr1 addr2; do | |
151 | printf -v ${addr} "%s" $(ipv6_explode ${!addr}) | |
ea878018 MT |
152 | |
153 | # Remove all colons | |
154 | printf -v ${addr} "${!addr//:/}" | |
4231f419 MT |
155 | done |
156 | ||
ab70371d MT |
157 | local i addr1_oct addr2_oct |
158 | for i in 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30; do | |
159 | addr1_oct="0x${addr1:${i}:2}" | |
160 | addr2_oct="0x${addr2:${i}:2}" | |
4231f419 | 161 | |
ab70371d MT |
162 | [[ ${addr1_oct} -gt ${addr2_oct} ]] && return ${EXIT_TRUE} |
163 | done | |
4231f419 | 164 | |
ab70371d | 165 | return ${EXIT_FALSE} |
4231f419 MT |
166 | } |
167 | ||
168 | function ipv6_hash() { | |
169 | local address=${1} | |
170 | ||
58fb41ee MT |
171 | assert isset address |
172 | ||
4231f419 MT |
173 | # Explode address |
174 | address=$(ipv6_explode ${address}) | |
175 | ||
176 | echo "${address//:/}" | |
177 | } | |
ab70371d MT |
178 | |
179 | function ipv6_get_network() { | |
180 | local addr=${1} | |
181 | assert isset addr | |
182 | ||
183 | # Check if a prefix (e.g. /64) is provided. | |
184 | local prefix=$(ip_get_prefix ${addr}) | |
185 | assert ipv6_prefix_is_valid ${prefix} | |
186 | ||
187 | local PREFIX6 | |
188 | eval $(ipcalc --ipv6 -p ${addr}) | |
189 | assert isset PREFIX6 | |
190 | ||
191 | print "${PREFIX6}/${prefix}" | |
192 | } | |
9390b61b SS |
193 | |
194 | function ipv6_6rd_format_address() { | |
195 | local isp_prefix="${1}" | |
196 | assert ipv6_is_valid "${isp_prefix}" | |
197 | ||
198 | local client_address="${2}" | |
199 | assert ipv4_is_valid "${client_address}" | |
200 | ||
201 | local prefix="$(ipv6_get_prefix "${isp_prefix}")" | |
202 | isp_prefix="$(ipv6_split_prefix "${isp_prefix}")" | |
203 | ||
204 | # This only works for prefix lengths up to 32 bit. | |
205 | assert [ "${prefix}" -le 32 ] | |
206 | assert [ "${prefix}" -gt 0 ] | |
207 | ||
208 | # Explode the address and throw away the second 32 bit. | |
209 | local address="$(ipv6_explode "${isp_prefix}")" | |
210 | ||
211 | client_address="$(ipv6_6rd_format_client_address ${client_address})" | |
212 | assert isset client_address | |
213 | ||
214 | local block1="0x${address:0:4}" | |
215 | local block2="0x${address:5:4}" | |
216 | local block3="0x${address:10:4}" | |
217 | local block4="0x${address:15:4}" | |
218 | ||
219 | address="$(( (${block1} << 48) + (${block2} << 32) + (${block3} << 16) + ${block4} ))" | |
220 | assert [ "${address}" -gt 0 ] | |
221 | ||
222 | block1="0x${client_address:0:4}" | |
223 | block2="0x${client_address:5:4}" | |
224 | ||
225 | client_address="$(( (${block1} << 48) + (${block2} << 32) ))" | |
226 | ||
227 | # Fix for numbers that are interpreted by bash as negative | |
228 | # numbers and therefore filled up with ones when shifted to | |
229 | # the right. Weird. | |
230 | if [ "${client_address}" -gt 0 ]; then | |
231 | client_address="$(( ${client_address} >> ${prefix} ))" | |
232 | else | |
233 | local bitmask="$(( 1 << 63 ))" | |
234 | client_address="$(( ${client_address} >> 1 ))" | |
235 | client_address="$(( ${client_address} ^ ${bitmask} ))" | |
236 | client_address="$(( ${client_address} >> $(( ${prefix} - 1 )) ))" | |
237 | fi | |
238 | assert [ "${client_address}" -gt 0 ] | |
239 | ||
240 | # XOR everything together | |
241 | address="$(( ${address} ^ ${client_address} ))" | |
242 | prefix="$(( ${prefix} + 32 ))" | |
243 | ||
244 | local block formatted_address=":" | |
245 | while [ ${address} -gt 0 ]; do | |
246 | printf -v block "%x" "$(( ${address} & 0xffff ))" | |
247 | formatted_address="${block}:${formatted_address}" | |
248 | ||
249 | address="$(( ${address} >> 16 ))" | |
250 | done | |
251 | ||
252 | assert ipv6_is_valid "${formatted_address}" | |
253 | ||
254 | # Implode the output IP address. | |
255 | formatted_address="$(ipv6_implode "${formatted_address}")" | |
256 | ||
257 | print "${formatted_address}/${prefix}" | |
258 | } | |
259 | ||
260 | function ipv6_6rd_format_client_address() { | |
261 | local address="${1}" | |
262 | assert isset address | |
263 | ||
264 | print "%02x%02x:%02x%02x" ${address//\./ } | |
265 | } |