-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnet_ip.php
301 lines (249 loc) · 7.6 KB
/
net_ip.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
<?php
class Net_Ip
{
const V6 = 6;
const V4 = 4;
/**
* Validate an IP address
*
* @param string $address IP Address in presentation format
* @param constant $version IP version Net_Ip::V4 | Net_Ip::V6
*
* @return boolean
* @throws Exception
*/
public static function validate($address, $version = null)
{
switch ($version) {
case self::V4:
return self::validate4($address);
break;
case self::V6:
return self::validate6($address);
break;
case null:
return self::version($address) === false ? false : true;
break;
default:
throw new Exception("Invalid version");
break;
}
return false;
}
/**
* Validate a netmask in string notation
*
* @param string $netmask IP Netmask in presentation format
* @param constant $version IP version Net_Ip::V4 | Net_Ip::V6
*
* @return boolean
* @throws Exception
*/
public static function validateNetmask($netmask, $version = null)
{
if ($version === null && !($version = self::version($netmask))) {
return false;
}
try {
$bits = self::netmask2bitmask($netmask);
} catch (Exception $e) {
return false;
}
switch ($version) {
case V4:
($bits >= 0 && $bits <= 32) ? true : false;
break;
case V6:
($bits >= 0 && $bits <= 128) ? true : false;
break;
default:
throw new Exception("Invalid version");
break;
}
return false;
}
/**
* Determines if an address is in a given network
*
* @param string $address Address in presentation format
* @param string $network Network in CIDR notation
*
* @return boolean
* @throws Exception
*/
public static function inNetwork($address, $network)
{
if (!self::validate($address)) {
throw new Exception("Invalid address");
}
list($networkAddress, $bitmask) = explode('/', $network);
if (strncmp(ip2bin($address), ip2bin($networkAddress), $bitmask) == 0) {
return true;
}
return false;
}
/**
* Determines if an address falls in a given range
*
* @param string $address Address in presentation format
* @param string $start Start address in presentation format
* @param string $end End address in presentation format
*
* @return boolean
* @throws Exception
*/
public static function inRange($address, $start, $end)
{
if (!self::validate($address)) {
throw new Exception("Invalid address");
}
if (!self::validate($start)) {
throw new Exception("Invalid start address");
}
if (!self::validate($end)) {
throw new Exception("Invalid end address");
}
if (inet_pton($address) >= inet_pton($start)
&& inet_pton($address) <= inet_pton($end)) {
return true;
}
return false;
}
/**
* Compress an IPv6 Address
*
* @param string $address IPv6 Address in presentation format
*
* @return string IPv6 Address in compressed presentation format
* @throws Exception
*/
public static function compress($address)
{
if (!self::validate($address, self::V6)) {
throw new Exception("Only IPv6 addresses can be compressed");
}
return inet_ntop(inet_pton($address));
}
/**
* Uncompress an IPv6 Address
*
* @param string $address IPv6 Address in presentation format
*
* @return string IPv6 Address in uncompressed presentation format
* @throws Exception
*/
public static function uncompress($address)
{
if (!self::validate($address, self::V6)) {
throw new Exception("Only IPv6 addresses can be compressed");
}
$address = inet_pton($address);
$return = '';
foreach (str_split($address) as $chunk) {
$return .= str_pad(dechex(ord($chunk)), 2, '0', STR_PAD_LEFT);
}
return implode(':', str_split($return, 4));
}
/**
* Get the number of netmask bits from a netmask in presentation format
*
* @param string $netmask Netmask in presentation format
*
* @return integer Number of mask bits
* @throws Exception
*/
public static function netmask2Bitmask($netmask)
{
if (!self::validate($netmask)) {
throw new Exception("Invalid netmask format");
}
$binString = self::ip2bin($netmask);
if (0 === preg_match('/^(1{0,})(0{0,})$/', $binString, $matches)) {
throw new Exception("Invalid netmask");
}
return strlen($matches[1]);
}
/**
* Get the IP version of an address or boolean false if it is not valid
*
* @param string $address IP address in presentation format
*
* @return integer|boolean Class constant for type or false
*/
public static function version($address)
{
if (self::validate4($address)) {
return self::V4;
}
if (self::validate6($address)) {
return self::V6;
}
return false;
}
/**
* Convert an IP in presentation format to it's binary string
*
* @param string $address IPv4 or IPv6 address in presentation format
*
* @return string Address in 32 or 128 length binary string (1s and 0s)
* @throws Exception
*/
protected static function ip2bin($address)
{
if (!self::validate($address)) {
throw new Exception("Invalid address for binary conversion");
}
$bin = '';
$address = inet_pton($address);
foreach (str_split($address) as $char) {
$bin .= str_pad(decbin(ord($char)), 8, '0', STR_PAD_LEFT);
}
return $bin;
}
/**
* Convert an IP in binary string to presentation format
*
* @param string $bin IPv4 or IPv6 address in binary string
*
* @return string Address in presentation format
* @throws Exception
*/
protected static function bin2ip($bin)
{
if ((strlen($bin) !== 32 && strlen($bin) !== 128)
|| (1 === preg_match('/[^01]/', $bin))) {
throw new Exception("Invalid binary string for address conversion");
}
$address = '';
foreach (str_split($bin, 8) as $byte) {
$address .= chr(bindec($byte));
}
return inet_ntop($address);
}
/**
* Validates an IPv4 address
*
* @param string $address IPv4 address in presentation format
*
* @return boolean
*/
protected static function validate4($address)
{
return filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)
? true
: false;
}
/**
* Validates an IPv6 address
*
* @param string $address IPv6 address in presentation format
*
* @return boolean
*/
protected static function validate6($address)
{
return filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)
? true
: false;
}
}