]>
Commit | Line | Data |
---|---|---|
8838c71a MT |
1 | #!/bin/bash |
2 | ############################################################################### | |
3 | # # | |
4 | # IPFire.org - A linux based firewall # | |
5 | # Copyright (C) 2009 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 | ||
22 | ############################################################################### | |
23 | # General IP address manipulation functions | |
24 | # ip_encode - Encodes an IP to an integer | |
25 | # Parameters: ip address (e.g. 192.168.0.1) | |
26 | # Returns : integer | |
27 | # ip_decode - Decodes an integer to an IP | |
28 | # Parameters: integer | |
29 | # Returns : ip address | |
30 | # ip_valid - Checks if given IP is valid | |
31 | # Parameters: IP | |
32 | # Returns : boolean | |
33 | # | |
34 | # General subnet functions | |
35 | # ip_range - Enumerates members of an IP range | |
36 | # Parameters: ip range (e.g. 192.168.0.1-192.168.0.128) | |
37 | # Returns : several subnets/IPs | |
38 | # ip_range_explicit - Enumerates ALL IP addresses of an IP range | |
39 | # Parameters: ip range | |
40 | # Returns : several IPs | |
41 | # subnet_network - Calculates the network address of a CIDR | |
42 | # Parameters: CIDR network (e.g. 192.168.0.0/24) | |
43 | # Returns : Network address | |
44 | # subnet_broadcast - Calculates the broadcast address of a CIDR | |
45 | # Parameters: CIDR network | |
46 | # Returns : Broadcast address | |
47 | # ip_in_subnet - Checks if an IP is in given subnet | |
48 | # Parameters: IP address, subnet | |
49 | # Returns : Boolean | |
50 | # mask_to_cidr - Converts a subnet mask to cidr type | |
51 | # Parameters: subnet (e.g. 255.255.255.0) | |
52 | # Returns : CIDR (e.g. 24) | |
53 | # | |
54 | ||
55 | function ip_encode() { | |
56 | IFS=$(ifs .) | |
57 | ||
58 | local int=0 | |
59 | for field in $1; do | |
60 | int=$(( $(( $int << 8 )) | $field )) | |
61 | done | |
62 | ||
63 | echo $int | |
64 | IFS=$(ifs) | |
65 | } | |
66 | ||
67 | function ip_decode() { | |
68 | addr=$1 | |
69 | ||
70 | local x | |
71 | local y | |
72 | ||
73 | y=$(($addr & 255)) | |
74 | for x in 1 2 3; do | |
75 | addr=$(($addr >> 8)) | |
76 | y=$(($addr & 255)).$y | |
77 | done | |
78 | ||
79 | echo $y | |
80 | } | |
81 | ||
82 | function ip_range() { | |
83 | local first | |
84 | local last | |
85 | local l | |
86 | local x | |
87 | local y | |
88 | local z | |
89 | local vlsm | |
90 | ||
91 | case "$1" in | |
92 | !*) | |
93 | echo $1 | |
94 | return | |
95 | ;; | |
96 | [0-9]*.*.*.*-*.*.*.*) | |
97 | ;; | |
98 | *) | |
99 | echo $1 | |
100 | return | |
101 | ;; | |
102 | esac | |
103 | ||
104 | first=$(ip_encode ${1%-*}) | |
105 | last=$(ip_encode ${1#*-}) | |
106 | ||
107 | if [ $first -gt $last ]; then | |
108 | error "Invalid IP address range: $1" | |
109 | fi | |
110 | ||
111 | l=$(( $last + 1 )) | |
112 | ||
113 | while [ $l -gt $first ]; do | |
114 | vlsm= | |
115 | x=31 | |
116 | y=2 | |
117 | z=1 | |
118 | ||
119 | while [ $(( $first % $y )) -eq 0 ] && [ $l -gt $(( $first + $y )) ]; do | |
120 | vlsm=/$x | |
121 | x=$(( $x - 1 )) | |
122 | z=$y | |
123 | y=$(( $y * 2 )) | |
124 | done | |
125 | ||
126 | echo $(ip_decode $first)$vlsm | |
127 | first=$(($first + $z)) | |
128 | done | |
129 | } | |
130 | ||
131 | function ip_range_explicit() { | |
132 | local first | |
133 | local last | |
134 | ||
135 | case $1 in | |
136 | [0-9]*.*.*.*-*.*.*.*) | |
137 | ;; | |
138 | *) | |
139 | echo $1 | |
140 | return | |
141 | ;; | |
142 | esac | |
143 | ||
144 | first=$(ip_encode ${1%-*}) | |
145 | last=$(ip_encode ${1#*-}) | |
146 | ||
147 | if [ $first -gt $last ]; then | |
148 | error "Invalid IP address range: $1" | |
149 | fi | |
150 | ||
151 | while ! [ $first -gt $last ]; do | |
152 | echo $(ip_decode $first) | |
153 | first=$(($first + 1)) | |
154 | done | |
155 | } | |
156 | ||
157 | function _netmask() { | |
158 | local vlsm | |
159 | vlsm=${1#*/} | |
160 | [ $vlsm -eq 0 ] && echo 0 || echo $(( -1 << $(( 32 - $vlsm )) )) | |
161 | } | |
162 | ||
163 | function subnet_network() { | |
164 | local encodedaddr | |
165 | encodedaddr=$(ip_encode ${1%/*}) | |
166 | local netmask | |
167 | netmask=$(_netmask $1) | |
168 | ||
169 | echo $(ip_decode $(($encodedaddr & $netmask))) | |
170 | } | |
171 | ||
172 | function _broadcast() { | |
173 | local x | |
174 | x=$(( 32 - ${1#*/} )) | |
175 | [ $x -eq 32 ] && echo -1 || echo $(( $(( 1 << $x )) - 1 )) | |
176 | } | |
177 | ||
178 | function subnet_broadcast() { | |
179 | local encodedaddr | |
180 | encodedaddr=$(ip_encode ${1%/*}) | |
181 | local netmask | |
182 | netmask=$(_netmask $1) | |
183 | local broadcast | |
184 | broadcast=$(_broadcast $1) | |
185 | ||
186 | echo $(ip_decode $(( $(($encodedaddr & $netmask)) | $broadcast ))) | |
187 | } | |
188 | ||
189 | function ip_in_subnet() { | |
190 | local netmask | |
191 | netmask=$(_netmask $2) | |
192 | [ $(( $(ip_encode $1) & $netmask)) = $(( $(ip_encode ${2%/*}) & $netmask )) ] | |
193 | } | |
194 | ||
195 | function mask_to_cidr() { | |
196 | local mask | |
197 | mask=$(ip_encode $1) | |
198 | local cidr | |
199 | cidr=0 | |
200 | local x | |
201 | x=$(( 128 << 24 )) # 0x80000000 | |
202 | ||
203 | while [ $(( $x & $mask )) -ne 0 ]; do | |
204 | [ $mask -eq $x ] && mask=0 || mask=$(( $mask << 1 )) | |
205 | cidr=$(($cidr + 1)) | |
206 | done | |
207 | ||
208 | if [ $(( $mask & 2147483647 )) -ne 0 ]; then # 2147483647 = 0x7fffffff | |
209 | echo "Invalid net mask: $1" >&2 | |
210 | else | |
211 | echo $cidr | |
212 | fi | |
213 | } | |
214 | ||
215 | function ip_valid() { | |
216 | local x | |
217 | IFS=$(ifs .) | |
218 | for x in $1; do | |
219 | case $x in | |
220 | [0-9]|[0-9][0-9]|[1-2][0-9][0-9]) | |
221 | [ $x -lt 256 ] || { IFS=$(ifs); return 1; } | |
222 | ;; | |
223 | *) | |
224 | IFS=$(ifs) | |
225 | return 1 | |
226 | ;; | |
227 | esac | |
228 | done | |
229 | IFS=$(ifs) | |
230 | return 0 | |
231 | } |