ipadmin 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/eui.rb ADDED
@@ -0,0 +1,381 @@
1
+ =begin rdoc
2
+ Copyright (c) 2006 Dustin Spinhirne -
3
+ Licensed under the same terms as Ruby, No Warranty is provided.
4
+ =end
5
+
6
+
7
+ module IPAdmin
8
+ class EUI
9
+
10
+ # instance variables
11
+ # @type - eui-48 or eui-64
12
+ # @oui - Organizationally Unique Identifier
13
+ # @ei - Extention Identifier
14
+
15
+ #==============================================================================#
16
+ # initialize()
17
+ #==============================================================================#
18
+
19
+ # - Arguments:
20
+ # * Hash with the following fields:
21
+ # - :EUI -- Extended Unique Identifier - String (optional)
22
+ # - :PackedEUI -- Integer representing an Extended Unique Identifier (optional)
23
+ # - :Length -- bit length of PackedEUI - Integer (optional)
24
+ #
25
+ # - Note:
26
+ # * At a minimum, EUI or PackedEUI must be provided.
27
+ # * PackedEUI takes precedence over EUI.
28
+ # * Length is only needed when using PackedEUI
29
+ #
30
+ # Example:
31
+ # addr = IPAdmin::EUI.new(:EUI => 'aa-bb-cc-dd-ee-ff')
32
+ # addr = IPAdmin::EUI.new(:EUI => 'aa:bb:cc:dd:ee:ff')
33
+ # addr = IPAdmin::EUI.new(:EUI => 'aabb.ccdd.eeff')
34
+ # addr = IPAdmin::EUI.new(:EUI => 'aa-bb-cc-dd-ee-ff-00-01')
35
+ #
36
+ def initialize(options)
37
+ if (!options.kind_of? Hash)
38
+ raise ArgumentError, "Expected Hash, but #{options.class} provided."
39
+ end
40
+
41
+ if (options.has_key?(:PackedEUI))
42
+ packed_eui = options[:PackedEUI]
43
+
44
+ if (options.has_key?(:Length) && options[:Length].kind_of?(Integer))
45
+ @type = options[:Length]
46
+ @type = 48 if (@type != 48 && @type != 64)
47
+ else
48
+ @type = 48
49
+ end
50
+
51
+ if (packed_eui.kind_of?(Integer))
52
+ if (@type == 48)
53
+ @oui = packed_eui >> 24
54
+ @ei = packed_eui & 0xffffff
55
+ else
56
+ @oui = packed_eui >> 40
57
+ @ei = packed_eui & 0xffffffffff
58
+ end
59
+ else
60
+ raise ArgumentError, "Expected Integer, but #{eui.class} " +
61
+ "provided for argument :PackedEUI."
62
+ end
63
+
64
+ elsif(options.has_key?(:EUI))
65
+ eui = options[:EUI]
66
+
67
+ if (eui.kind_of?(String))
68
+ # validate
69
+ IPAdmin.validate_eui(:EUI => eui)
70
+
71
+ # remove formatting characters
72
+ eui.gsub!(/[\.\:\-]/, '')
73
+
74
+ # check if eui-48 or eui-64
75
+ if (eui.length == 12)
76
+ @type = 48
77
+ elsif (eui.length == 16)
78
+ @type = 64
79
+ else
80
+ raise "#{eui} is invalid (address is neither EUI-48 nor EUI-64)."
81
+ end
82
+
83
+ # split into oui & ei, pack, and store
84
+ @oui = eui.slice!(0..5).to_i(16)
85
+ @ei = eui.to_i(16)
86
+
87
+ else
88
+ raise ArgumentError, "Expected String, but #{eui.class} " +
89
+ "provided for argument :EUI."
90
+ end
91
+
92
+ else
93
+ raise ArgumentError, "Missing argument: [EUI|PackedEUI]."
94
+ end
95
+
96
+ end
97
+
98
+ #======================================#
99
+ #
100
+ #======================================#
101
+
102
+
103
+ #==============================================================================#
104
+ # address()
105
+ #==============================================================================#
106
+
107
+ # Returns EUI address.
108
+ #
109
+ # - Arguments:
110
+ # * Optional hash with the following fields:
111
+ # - :Delimiter -- delimitation character. valid values are (-,:,and .) (optional)
112
+ #
113
+ # - Returns:
114
+ # * String
115
+ #
116
+ # Example:
117
+ # puts addr.address(:Delimiter => '.') --> 'aabb.ccdd.eeff'
118
+ #
119
+ def address(options=nil)
120
+ delimiter = '-'
121
+
122
+ octets = []
123
+ octets.concat(unpack_oui)
124
+ octets.concat(unpack_ei)
125
+
126
+ if (options)
127
+ if (!options.kind_of? Hash)
128
+ raise ArgumentError, "Expected Hash, but #{options.class} provided."
129
+ end
130
+
131
+ if (options.has_key?(:Delimiter))
132
+ delimiter = options[:Delimiter]
133
+ delimiter = '-' if (delimiter != '-' && delimiter != ':' && delimiter != '.' )
134
+ end
135
+ end
136
+
137
+ if (delimiter == '-' || delimiter == ':')
138
+ address = octets.join(delimiter)
139
+ elsif (delimiter == '.')
140
+ toggle = 0
141
+ octets.each do |x|
142
+ if (!address)
143
+ address = x
144
+ toggle = 1
145
+ elsif (toggle == 0)
146
+ address = address << '.' << x
147
+ toggle = 1
148
+ else
149
+ address = address << x
150
+ toggle = 0
151
+ end
152
+ end
153
+
154
+ end
155
+
156
+ return(address)
157
+ end
158
+
159
+ #======================================#
160
+ #
161
+ #======================================#
162
+
163
+
164
+ #==============================================================================#
165
+ # ei()
166
+ #==============================================================================#
167
+
168
+ # Returns Extended Identifier portion of an EUI address (the vendor assigned ID).
169
+ #
170
+ # - Arguments:
171
+ # * Optional hash with the following fields:
172
+ # - :Delimiter -- delimitation character. valid values are (-, and :) (optional)
173
+ #
174
+ # - Returns:
175
+ # * String
176
+ #
177
+ # Example:
178
+ # puts addr.ei(:Delimiter => '-') --> 'aa-bb-cc'
179
+ #
180
+ def ei(options=nil)
181
+ octets = unpack_ei()
182
+ delimiter = '-'
183
+
184
+ if (options)
185
+ if (!options.kind_of? Hash)
186
+ raise ArgumentError, "Expected Hash, but #{options.class} provided."
187
+ end
188
+
189
+ if (options.has_key?(:Delimiter))
190
+ if (options[:Delimiter] == ':')
191
+ delimiter = options[:Delimiter]
192
+ end
193
+ end
194
+ end
195
+ ei = octets.join(delimiter)
196
+
197
+ return(ei)
198
+ end
199
+
200
+ #======================================#
201
+ #
202
+ #======================================#
203
+
204
+
205
+ #==============================================================================#
206
+ # link_local()
207
+ #==============================================================================#
208
+
209
+ # Provide an IPv6 Link Local address based on the current EUI address.
210
+ #
211
+ # - Arguments:
212
+ # * Optional hash with the following fields:
213
+ # - :Short -- if true, return IPv6 addresses in short-hand notation (optional)
214
+ # - :Objectify -- if true, return CIDR objects (optional)
215
+ #
216
+ # - Returns:
217
+ # * String
218
+ #
219
+ # Example:
220
+ # puts addr.link_local() --> fe80:0000:0000:0000:aabb:ccff:fedd:eeff
221
+ #
222
+ def link_local(options=nil)
223
+ objectify = false
224
+ short = false
225
+
226
+ if (options)
227
+ if (!options.kind_of? Hash)
228
+ raise ArgumentError, "Expected Hash, but #{options.class} provided."
229
+ end
230
+
231
+ if (options.has_key?(:Objectify) && options[:Objectify] == true)
232
+ objectify = true
233
+ end
234
+
235
+ if (options.has_key?(:Short) && options[:Short] == true)
236
+ short = true
237
+ end
238
+ end
239
+
240
+ if (@type == 48)
241
+ link_local = @ei | 0xfffe000000 | (@oui << 40)
242
+ else
243
+ link_local = @ei | (@oui << 40)
244
+ end
245
+ link_local = link_local | (0xfe80 << 112)
246
+
247
+ if (!objectify)
248
+ link_local = IPAdmin.unpack_ip_addr(:Integer => link_local, :Version => 6)
249
+ link_local = IPAdmin.shorten(link_local) if (short)
250
+ else
251
+ link_local = IPAdmin::CIDR.new(:PackedIP => link_local,
252
+ :Version => 6)
253
+ end
254
+
255
+ return(link_local)
256
+ end
257
+
258
+ #======================================#
259
+ #
260
+ #======================================#
261
+
262
+
263
+ #==============================================================================#
264
+ # oui()
265
+ #==============================================================================#
266
+
267
+ # Returns Organizationally Unique Identifier portion of an EUI address (the vendor ID).
268
+ #
269
+ # - Arguments:
270
+ # * Optional hash with the following fields:
271
+ # - :Delimiter -- delimitation character. valid values are (-, and :) (optional)
272
+ #
273
+ # - Returns:
274
+ # * String
275
+ #
276
+ # Example:
277
+ # puts addr.oui(:Delimiter => '-') --> 'dd-ee-ff'
278
+ #
279
+ def oui(options=nil)
280
+ octets = unpack_oui()
281
+ delimiter = '-'
282
+
283
+ if (options)
284
+ if (!options.kind_of? Hash)
285
+ raise ArgumentError, "Expected Hash, but #{options.class} provided."
286
+ end
287
+
288
+ if (options.has_key?(:Delimiter))
289
+ if (options[:Delimiter] == ':')
290
+ delimiter = options[:Delimiter]
291
+ end
292
+ end
293
+ end
294
+ oui = octets.join(delimiter)
295
+
296
+ return(oui)
297
+ end
298
+
299
+ #======================================#
300
+ #
301
+ #======================================#
302
+
303
+
304
+ #==============================================================================#
305
+ # type()
306
+ #==============================================================================#
307
+
308
+ # Provide address type (EUI-48 or EUI-64).
309
+ #
310
+ # - Arguments:
311
+ # * none
312
+ #
313
+ # - Returns:
314
+ # * String
315
+ #
316
+ # Example:
317
+ # puts addr.type --> EUI-48
318
+ #
319
+ def type()
320
+ if (@type == 48)
321
+ return('EUI-48')
322
+ else
323
+ return('EUI-64')
324
+ end
325
+ end
326
+
327
+ #======================================#
328
+ #
329
+ #======================================#
330
+
331
+
332
+
333
+ # PRIVATE METHODS
334
+ private
335
+
336
+ #==============================================================================#
337
+ # unpack_ei()
338
+ #==============================================================================#
339
+
340
+ def unpack_ei()
341
+ hex = @ei
342
+ octets = []
343
+ loop_count = (@type - 24)/8
344
+ loop_count.times do
345
+ octet = (hex & 0xff).to_s(16)
346
+ octet = '0' << octet if (octet.length != 2)
347
+ octets.unshift(octet)
348
+ hex = hex >> 8
349
+ end
350
+ return(octets)
351
+ end
352
+
353
+ #======================================#
354
+ #
355
+ #======================================#
356
+
357
+
358
+ #==============================================================================#
359
+ # unpack_oui()
360
+ #==============================================================================#
361
+
362
+ def unpack_oui()
363
+ hex = @oui
364
+ octets = []
365
+ 3.times do
366
+ octet = (hex & 0xff).to_s(16)
367
+ octet = '0' << octet if (octet.length != 2)
368
+ octets.unshift(octet)
369
+ hex = hex >> 8
370
+ end
371
+ return(octets)
372
+ end
373
+
374
+ #======================================#
375
+ #
376
+ #======================================#
377
+
378
+ end
379
+
380
+ end # module IPAdmin
381
+ __END__
data/lib/ip_admin.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  =begin rdoc
2
- Copyright (c) 2006 Dustin Spinhirne <http://www.spinhirne.com> -
2
+ Copyright (c) 2006 Dustin Spinhirne -
3
3
  Licensed under the same terms as Ruby, No Warranty is provided.
4
4
  =end
5
5
 
@@ -7,5 +7,6 @@
7
7
  require File.join(File.dirname(__FILE__), 'methods.rb')
8
8
  require File.join(File.dirname(__FILE__), 'cidr.rb')
9
9
  require File.join(File.dirname(__FILE__), 'tree.rb')
10
+ require File.join(File.dirname(__FILE__), 'eui.rb')
10
11
 
11
12
  __END__
data/lib/methods.rb CHANGED
@@ -154,6 +154,12 @@ module_function :create_net_struct
154
154
  # - Returns:
155
155
  # * Array of CIDR or NetStruct objects
156
156
  #
157
+ # - Notes:
158
+ # * I have designed this with enough flexibility that you can pass in CIDR
159
+ # addresses that arent even related (ex. 192.168.1.0/26, 192.168.1.64/26,
160
+ # 10.1.0.0/26, 10.1.0.64/26) and they will be merged properly (ie 192.168.1.0/25,
161
+ # and 10.1.0.0/25 would be returned).
162
+ #
157
163
  # Example:
158
164
  # supernets = IPAdmin.merge(:List => list)
159
165
  #
@@ -171,11 +177,11 @@ def merge(options)
171
177
  raise ArgumentError, "Missing argument: List."
172
178
  end
173
179
 
174
- if (options.has_key?(:Short))
180
+ if (options.has_key?(:Short) && options[:Short] == true)
175
181
  short = true
176
182
  end
177
183
 
178
- if (options.has_key?(:Objectify))
184
+ if (options.has_key?(:Objectify) && options[:Objectify] == true)
179
185
  objectify = true
180
186
  end
181
187
 
@@ -685,11 +691,11 @@ def range(options)
685
691
  bitstep = options[:Bitstep]
686
692
  end
687
693
 
688
- if( options.has_key?(:Objectify) )
694
+ if( options.has_key?(:Objectify) && options[:Objectify] == true )
689
695
  objectify = true
690
696
  end
691
697
 
692
- if( options.has_key?(:Short) )
698
+ if( options.has_key?(:Short) && options[:Short] == true )
693
699
  short = true
694
700
  end
695
701
 
@@ -1115,6 +1121,71 @@ module_function :unshorten
1115
1121
  #======================================#
1116
1122
 
1117
1123
 
1124
+ #==============================================================================#
1125
+ # validate_eui()
1126
+ #==============================================================================#
1127
+
1128
+ # Validate an EUI-48 or EUI-64 address.
1129
+ #
1130
+ # - Arguments
1131
+ # * Hash with the following fields:
1132
+ # - :EUI -- Address to validate - String
1133
+ #
1134
+ # - Returns:
1135
+ # * True
1136
+ #
1137
+ # - Example:
1138
+ # * IPAdmin.validate_eui(:EUI => '01-00-5e-12-34-56')
1139
+ #
1140
+ def validate_eui(options)
1141
+ if (!options.kind_of? Hash)
1142
+ raise ArgumentError, "Expected Hash, but #{options.class} provided."
1143
+ end
1144
+
1145
+ if (!options.has_key?(:EUI))
1146
+ raise ArgumentError, "Missing argument: EUI."
1147
+ end
1148
+ eui = options[:EUI]
1149
+
1150
+ if (eui.kind_of?(String))
1151
+ # check for invalid characters
1152
+ if (eui =~ /[^0-9a-fA-f\.\-\:]/)
1153
+ raise "#{eui} is invalid (contains invalid characters)."
1154
+ end
1155
+
1156
+ # split on formatting characters & check lengths
1157
+ if (eui =~ /\-/)
1158
+ fields = eui.split('-')
1159
+ if (fields.length != 6 && fields.length != 8)
1160
+ raise "#{eui} is invalid (unrecognized formatting)."
1161
+ end
1162
+ elsif (eui =~ /\:/)
1163
+ fields = eui.split(':')
1164
+ if (fields.length != 6 && fields.length != 8)
1165
+ raise "#{eui} is invalid (unrecognized formatting)."
1166
+ end
1167
+ elsif (eui =~ /\./)
1168
+ fields = eui.split('.')
1169
+ if (fields.length != 3 && fields.length != 4)
1170
+ raise "#{eui} is invalid (unrecognized formatting)."
1171
+ end
1172
+ else
1173
+ raise "#{eui} is invalid (unrecognized formatting)."
1174
+ end
1175
+
1176
+ else
1177
+ raise ArgumentError, "Expected String, but #{eui.class} " +
1178
+ "provided for argument :EUI."
1179
+ end
1180
+ return(true)
1181
+ end
1182
+ module_function :validate_eui
1183
+
1184
+ #======================================#
1185
+ #
1186
+ #======================================#
1187
+
1188
+
1118
1189
  #==============================================================================#
1119
1190
  # validate_ip_addr()
1120
1191
  #==============================================================================#
@@ -1432,737 +1503,6 @@ NetStruct = Struct.new(:network, :netmask, :version, :object, :subnets)
1432
1503
  #======================================#
1433
1504
 
1434
1505
 
1435
-
1436
-
1437
-
1438
- # DEPRICATED
1439
-
1440
- #==============================================================================#
1441
- # arpa()
1442
- #==============================================================================#
1443
-
1444
- # DEPRICATED - USE CIDR.arpa:
1445
- # Using the provided CIDR object,
1446
- # return either an in-addr.arpa. or ip6.arpa. string. The netmask will be used
1447
- # to determine the length of the returned arpa string.
1448
- #
1449
- # - Arguments:
1450
- # * CIDR object
1451
- #
1452
- # - Returns:
1453
- # * String
1454
- #
1455
- # - Notes:
1456
- # * IPAdmin.arpa will use the original IP address passed during the initialization
1457
- # of the CIDR objects. This IP can be found using the CIDR.ip() method.
1458
- #
1459
- # Example:
1460
- # arpa = IPAdmin.arpa(cidr)
1461
- #
1462
- def arpa(object)
1463
-
1464
- if (!object.kind_of? IPAdmin::CIDR)
1465
- raise ArgumentError, "Expected IPAdmin::CIDR object, " +
1466
- "but #{object.class} provided."
1467
- end
1468
-
1469
- base = object.ip()
1470
- netmask = object.bits()
1471
-
1472
- if (object.version == 4)
1473
- net = base.split('.')
1474
-
1475
- if (netmask)
1476
- while (netmask < 32)
1477
- net.pop
1478
- netmask = netmask + 8
1479
- end
1480
- end
1481
-
1482
- arpa = net.reverse.join('.')
1483
- arpa << ".in-addr.arpa."
1484
-
1485
- elsif (object.version == 6)
1486
- fields = base.split(':')
1487
- net = []
1488
- fields.each do |field|
1489
- (field.split("")).each do |x|
1490
- net.push(x)
1491
- end
1492
- end
1493
-
1494
- if (netmask)
1495
- while (netmask < 128)
1496
- net.pop
1497
- netmask = netmask + 4
1498
- end
1499
- end
1500
-
1501
- arpa = net.reverse.join('.')
1502
- arpa << ".ip6.arpa."
1503
-
1504
- end
1505
-
1506
- return(arpa)
1507
- end
1508
- module_function :arpa
1509
-
1510
- #======================================#
1511
- #
1512
- #======================================#
1513
-
1514
- #==============================================================================#
1515
- # validate_ipv4_addr()
1516
- #==============================================================================#
1517
-
1518
- # DEPRICATED - USE validate_ip_addr INSTEAD
1519
- # Validate IPv4 addresses. The address should not contain a netmask.
1520
- #
1521
- # - Arguments:
1522
- # * IPv4 address
1523
- #
1524
- # - Returns:
1525
- # * packed IP on valid, or exception on error.
1526
- #
1527
- # Example:
1528
- # IPAdmin.validate_ipv4_addr('192.168.1.1')
1529
- #
1530
- def validate_ipv4_addr(ip)
1531
-
1532
- # is this a string?
1533
- unless (ip.kind_of? String)
1534
- raise ArgumentError, "Expected String, but #{ip.class} provided."
1535
- end
1536
-
1537
- # check validity of characters in the addr
1538
- if ( (ip =~ /\.{2,}?/ ) || (ip =~ /[^0-9\.]/) )
1539
- raise "#{ip} is not a valid IPv4 address."
1540
- end
1541
-
1542
- # do we have 4 octets?
1543
- octets = ip.split( /\./ ).reverse
1544
- if (octets.length != 4)
1545
- raise "#{ip} is not a valid IPv4 address."
1546
- end
1547
-
1548
- # are octets in range 0..255?
1549
- packed_ip = 0
1550
- (0..3).each do |x|
1551
- octets[x] = octets[x].to_i
1552
- unless ( (octets[x] >= 0) && (octets[x] < 256 ) )
1553
- raise "#{ip} is not a valid IPv4 address."
1554
- end
1555
- octets[x] = octets[x] << 8*x
1556
- packed_ip = packed_ip | octets[x]
1557
- end
1558
-
1559
- # dont allow first octet to be 0
1560
- if (octets[3] == 0)
1561
- raise "#{ip} is not a valid IPv4 address."
1562
- end
1563
-
1564
- return(packed_ip)
1565
-
1566
- end
1567
- module_function :validate_ipv4_addr
1568
-
1569
- #======================================#
1570
- #
1571
- #======================================#
1572
-
1573
-
1574
- #==============================================================================#
1575
- # validate_ipv4_netmask()
1576
- #==============================================================================#
1577
-
1578
- # DEPRICATED - USE validate_ip_netmask INSTEAD
1579
- # Validate IPv4 Netmask.
1580
- #
1581
- # - Arguments:
1582
- # * IPv4 netmask in cidr or extended notation
1583
- #
1584
- # - Returns:
1585
- # * packed netmask on valid, or exception on error.
1586
- #
1587
- # Example:
1588
- # IPAdmin.validate_ipv4_netmask('255.255.255.0')
1589
- # IPAdmin.validate_ipv4_netmask('24')
1590
- # IPAdmin.validate_ipv4_netmask('/24')
1591
- # IPAdmin.validate_ipv4_netmask(24)
1592
- #
1593
- def validate_ipv4_netmask(netmask)
1594
- all_f = 2**32 - 1
1595
- packed_mask = nil
1596
-
1597
- # is this a CIDR or Extended mask?
1598
- if(netmask =~ /\./)
1599
- # validate & pack extended mask
1600
- begin
1601
- validate_ipv4_addr(netmask)
1602
- packed_netmask = pack_ipv4_addr(netmask)
1603
-
1604
- rescue Exception
1605
- raise "#{netmask} is not a valid IPv4 netmask."
1606
- end
1607
-
1608
- # cycle through the bits of hostmask and compare
1609
- # with packed_mask. when we hit the firt '1' within
1610
- # packed_mask (our netmask boundary), xor hostmask and
1611
- # packed_mask. the result should be all 1's. this whole
1612
- # process is in place to make sure that we dont have
1613
- # and crazy masks such as 255.254.255.0
1614
- hostmask = 1
1615
- 32.times do
1616
- check = packed_netmask & hostmask
1617
- if ( check != 0)
1618
- hostmask = hostmask >> 1
1619
- unless ( (packed_netmask ^ hostmask) == all_f)
1620
- raise "#{netmask} is not a valid IPv4 netmask."
1621
- end
1622
- break
1623
- else
1624
- hostmask = hostmask << 1
1625
- hostmask = hostmask | 1
1626
- end
1627
- end
1628
-
1629
- else
1630
- # remove '/' if present
1631
- if (netmask =~ /^\// )
1632
- netmask[0] = " "
1633
- netmask.lstrip!
1634
- end
1635
-
1636
- # check if we have any non numeric characters
1637
- if (netmask =~ /\D/)
1638
- raise "#{netmask} is not a valid IPv4 netmask."
1639
- end
1640
-
1641
- # are we between 1 and 32 inclusive
1642
- if (netmask.kind_of? String)
1643
- netmask = netmask.to_i
1644
- end
1645
-
1646
- if ( (netmask > 32) || (netmask == 0) )
1647
- raise "#{netmask} is not a valid IPv4 netmask."
1648
- end
1649
-
1650
- packed_netmask = all_f ^ (all_f >> netmask)
1651
- end
1652
-
1653
- return(packed_netmask)
1654
- end
1655
- module_function :validate_ipv4_netmask
1656
-
1657
- #======================================#
1658
- #
1659
- #======================================#
1660
-
1661
-
1662
- #==============================================================================#
1663
- # validate_ipv6_addr()
1664
- #==============================================================================#
1665
-
1666
- # DEPRICATED - USE validate_ip_addr INSTEAD
1667
- # Validate IPv6 addresses. The address should not contain a netmask.
1668
- #
1669
- # - Arguments:
1670
- # * IPv6 address
1671
- #
1672
- # - Returns:
1673
- # * packed IP on valid, or exception on error.
1674
- #
1675
- # Example:
1676
- # IPAdmin.validate_ipv6_addr('fec0::')
1677
- #
1678
- def validate_ipv6_addr(ip)
1679
- # is this a string?
1680
- unless (ip.kind_of? String)
1681
- raise ArgumentError, "Expected String, but #{ip.class} provided."
1682
- end
1683
-
1684
- # check validity of characters in the addr
1685
- if ( (ip =~ /:{3,}?/ ) || (ip =~ /[^0-9a-fA-F:]/) )
1686
- raise "#{ip} is not a valid IPv6 address."
1687
- end
1688
-
1689
- # look for a '::' to see if this address is in shorthand
1690
- # if found, split on it & make sure that we have at most
1691
- # two elements
1692
- if (ip =~ /::/)
1693
- shrthnd = ip.split( /::/ )
1694
- unless ( (shrthnd.length > 0) && (shrthnd.length < 3) )
1695
- raise "#{ip} is not a valid IPv6 address."
1696
- end
1697
- end
1698
-
1699
- if (shrthnd)
1700
- # if shorthand, we should have between 1 and 7
1701
- # hex fields
1702
- hex_fields = []
1703
- shrthnd.each do |x|
1704
- elements = x.split( /:/ )
1705
- elements.each {|x| hex_fields.push(x)}
1706
- end
1707
- if ( (hex_fields.length < 1) || (hex_fields.length > 7) )
1708
- raise "#{ip} is not a valid IPv6 address."
1709
- end
1710
-
1711
- else
1712
- # since no shorthand notation was detected we should
1713
- # have exactly 8 hex fields
1714
- hex_fields = ip.split( /:/ )
1715
- if (hex_fields.length != 8)
1716
- raise "#{ip} is not a valid IPv6 address."
1717
- end
1718
-
1719
- end
1720
-
1721
- # check that we have no more than 4 characters in each
1722
- # hex field
1723
- hex_fields.each do |x|
1724
- if (x.length > 4)
1725
- raise "#{ip} is not a valid IPv6 address."
1726
- end
1727
- end
1728
-
1729
- packed_ip = IPAdmin.pack_ipv6_addr(ip)
1730
- return(packed_ip)
1731
- end
1732
- module_function :validate_ipv6_addr
1733
-
1734
- #======================================#
1735
- #
1736
- #======================================#
1737
-
1738
-
1739
- #==============================================================================#
1740
- # validate_ipv6_netmask()
1741
- #==============================================================================#
1742
-
1743
- # DEPRICATED - USE validate_ip_netmask INSTEAD
1744
- # Validate IPv6 netmask.
1745
- #
1746
- # - Arguments:
1747
- # * IPv6 netmask in cidr notation
1748
- #
1749
- # - Returns:
1750
- # * packed netmask on valid, or exception on error.
1751
- #
1752
- # Example:
1753
- # IPAdmin.validate_ipv6_netmask('64')
1754
- # IPAdmin.validate_ipv6_netmask('/64')
1755
- # IPAdmin.validate_ipv6_netmask(64)
1756
- #
1757
- def validate_ipv6_netmask(netmask)
1758
- all_f = 2**128 -1
1759
-
1760
- # remove '/' if present
1761
- if (netmask =~ /^\// )
1762
- netmask[0] = " "
1763
- netmask.lstrip!
1764
- end
1765
-
1766
- if (netmask =~ /\D/)
1767
- raise "#{netmask} is not a valid IPv6 netmask."
1768
-
1769
- else
1770
- # are we between 1 and 128 inclusive
1771
- if (netmask.kind_of? String)
1772
- netmask = netmask.to_i
1773
- end
1774
-
1775
- if ( (netmask > 128) || (netmask == 0) )
1776
- raise "#{netmask} is not a valid IPv6 netmask."
1777
- end
1778
-
1779
- end
1780
-
1781
- packed_netmask = all_f ^ (all_f >> netmask)
1782
- return(packed_netmask)
1783
- end
1784
- module_function :validate_ipv6_netmask
1785
-
1786
- #======================================#
1787
- #
1788
- #======================================#
1789
-
1790
-
1791
- #==============================================================================#
1792
- # pack_ipv4_addr()
1793
- #==============================================================================#
1794
-
1795
- # DEPRICATED - USE pack_ip_addr INSTEAD
1796
- # Convert IPv4 addresses into an integer. No attempt at
1797
- # validation is performed.
1798
- #
1799
- # - Arguments:
1800
- # * IPv4 address
1801
- #
1802
- # - Returns:
1803
- # * packed IPv4 address or exception on error.
1804
- #
1805
- # Example:
1806
- # packed = IPAdmin.pack_ipv4_addr('192.168.1.1')
1807
- #
1808
- def pack_ipv4_addr(ip)
1809
-
1810
- # is this a string?
1811
- unless (ip.kind_of? String)
1812
- raise ArgumentError, "Expected String, but #{ip.class} provided."
1813
- end
1814
-
1815
- # pack our ip
1816
- octets = ip.split( /\./ ).reverse
1817
- packed_ip = 0
1818
-
1819
- (0..3).each do |x|
1820
- octets[x] = (octets[x]).to_i
1821
- octets[x] = octets[x] << 8*x
1822
- packed_ip = packed_ip | octets[x]
1823
- end
1824
-
1825
- return(packed_ip)
1826
- end
1827
- module_function :pack_ipv4_addr
1828
-
1829
- #======================================#
1830
- #
1831
- #======================================#
1832
-
1833
-
1834
- #==============================================================================#
1835
- # pack_ipv4_netmask()
1836
- #==============================================================================#
1837
-
1838
- # DEPRICATED - USE pack_ip_netmask INSTEAD
1839
- # Convert IPv4 netmask into an integer. Only very basic
1840
- # validation is performed.
1841
- #
1842
- # - Arguments:
1843
- # * IPv4 netmask in cidr or extended notation
1844
- #
1845
- # - Returns:
1846
- # * packed IPv4 netmask or exception on error.
1847
- #
1848
- # Example:
1849
- # packed = IPAdmin.pack_ipv4_netmask('255.255.255.0')
1850
- # packed = IPAdmin.pack_ipv4_netmask('24')
1851
- # packed = IPAdmin.pack_ipv4_netmask('/24')
1852
- # packed = IPAdmin.pack_ipv4_netmask(24)
1853
- #
1854
- def pack_ipv4_netmask(netmask)
1855
- all_f = 2**32-1
1856
-
1857
- # is this a CIDR or Extended mask?
1858
- if(netmask =~ /\./)
1859
- # pack extended mask
1860
- begin
1861
- packed_netmask = pack_ipv4_addr(netmask)
1862
- rescue Exception
1863
- raise "#{netmask} is not a valid IPv4 netmask."
1864
- end
1865
-
1866
- else
1867
- # remove '/' if present
1868
- if (netmask =~ /^\// )
1869
- netmask[0] = " "
1870
- netmask.lstrip!
1871
- end
1872
-
1873
- # check if we have any non numeric characters
1874
- if (netmask =~ /\D/)
1875
- raise "#{netmask} is not a valid IPv4 netmask."
1876
- end
1877
-
1878
- if (netmask.kind_of? String)
1879
- netmask = netmask.to_i
1880
- end
1881
-
1882
- packed_netmask = all_f ^ (all_f >> netmask)
1883
- end
1884
-
1885
- return(packed_netmask)
1886
- end
1887
- module_function :pack_ipv4_netmask
1888
-
1889
- #======================================#
1890
- #
1891
- #======================================#
1892
-
1893
-
1894
- #==============================================================================#
1895
- # pack_ipv6_addr()
1896
- #==============================================================================#
1897
-
1898
- # DEPRICATED - USE pack_ip_addr INSTEAD
1899
- # Convert IPv6 addresses into an integer. No attempt at
1900
- # validation is performed.
1901
- #
1902
- # - Arguments:
1903
- # * IPv6 address
1904
- #
1905
- # - Returns:
1906
- # * packed IPv6 address or exception on error.
1907
- #
1908
- # Example:
1909
- # packed = IPAdmin.pack_ipv6_addr('fec0::1')
1910
- #
1911
- def pack_ipv6_addr(ip)
1912
- # is this a string?
1913
- unless (ip.kind_of? String)
1914
- raise ArgumentError, "Expected String, but #{ip.class} provided."
1915
- end
1916
-
1917
- # look for a '::' to see if this address is in shorthand
1918
- # if found, split on it
1919
- hex_fields = []
1920
- if (ip =~ /::/)
1921
- shrthnd = ip.split( /::/ )
1922
- if (ip =~ /^::/)
1923
- sec_half = shrthnd[1].split( /:/ )
1924
- zero_pads = 8 - sec_half.length
1925
- (1..zero_pads).each {hex_fields.push('0')}
1926
- sec_half.each {|field| hex_fields.push(field)}
1927
- elsif (ip =~ /::$/)
1928
- hex_fields = shrthnd[0].split( /:/ )
1929
- zero_pads = 8 - hex_fields.length
1930
- (1..zero_pads).each {hex_fields.push('0')}
1931
- else
1932
- first_half = shrthnd[0].split( /:/ )
1933
- sec_half = shrthnd[1].split( /:/ )
1934
- zero_pads = 8 - (first_half.length + sec_half.length)
1935
- first_half.each {|field| hex_fields.push(field)}
1936
- (1..zero_pads).each {hex_fields.push('0')}
1937
- sec_half.each {|field| hex_fields.push(field)}
1938
- end
1939
-
1940
- else
1941
- hex_fields = ip.split( /:/ )
1942
- end
1943
-
1944
- # pack
1945
- hex_fields.reverse!
1946
- packed_ip = 0
1947
- (0..7).each do |x|
1948
- hex = hex_fields[x]
1949
- base16 = hex.to_i(16)
1950
-
1951
- base16 = base16 << 16*x
1952
- packed_ip = packed_ip | base16
1953
- end
1954
-
1955
-
1956
- return(packed_ip)
1957
1506
  end
1958
- module_function :pack_ipv6_addr
1959
-
1960
- #======================================#
1961
- #
1962
- #======================================#
1963
-
1964
-
1965
- #==============================================================================#
1966
- # pack_ipv6_netmask()
1967
- #==============================================================================#
1968
-
1969
- # DEPRICATED - USE pack_ip_netmask INSTEAD
1970
- # Convert IPv6 netmask into an integer. Only very basic
1971
- # validation is performed.
1972
- #
1973
- # - Arguments:
1974
- # * IPv6 netmask in cidr notation
1975
- #
1976
- # - Returns:
1977
- # * packed IPv6 netmask or exception on error.
1978
- #
1979
- # Example:
1980
- # packed = IPAdmin.pack_ipv6_netmask('64')
1981
- # packed = IPAdmin.pack_ipv6_netmask('/64')
1982
- # packed = IPAdmin.pack_ipv6_netmask(64)
1983
- #
1984
- def pack_ipv6_netmask(netmask)
1985
- all_f = 2**128-1
1986
-
1987
- # remove '/' if present
1988
- if (netmask =~ /^\// )
1989
- netmask[0] = " "
1990
- netmask.lstrip!
1991
- end
1992
-
1993
- if (netmask !~ /\D/)
1994
- # pack
1995
- if (netmask.kind_of? String)
1996
- netmask = netmask.to_i
1997
- end
1998
-
1999
- packed_netmask = all_f ^ (all_f >> netmask)
2000
-
2001
- else
2002
- raise "#{netmask} is not a valid IPv6 netmask."
2003
-
2004
- end
2005
-
2006
- return(packed_netmask)
2007
- end
2008
- module_function :pack_ipv6_netmask
2009
-
2010
- #======================================#
2011
- #
2012
- #======================================#
2013
-
2014
-
2015
- #==============================================================================#
2016
- # unpack_ipv4_addr()
2017
- #==============================================================================#
2018
-
2019
- # DEPRICATED - USE unpack_ip_addr INSTEAD
2020
- # Unack a packed IPv4 address back into a printable string. No attempt at
2021
- # validation is performed.
2022
- #
2023
- # - Arguments:
2024
- # * Byte-packed IPv4 address
2025
- #
2026
- # - Returns:
2027
- # * IPv4 address.
2028
- #
2029
- # Example:
2030
- # unpacked = IPAdmin.unpack_ipv4_addr(packed)
2031
- #
2032
- def unpack_ipv4_addr(packed_ip)
2033
- octets = []
2034
- (0..3).each do |x|
2035
- octets[x] = packed_ip & 0xFF
2036
- octets[x] = (octets[x]).to_s
2037
- packed_ip = packed_ip >> 8
2038
- end
2039
-
2040
- octets.reverse!
2041
- ip = octets.join('.')
2042
-
2043
- return(ip)
2044
- end
2045
- module_function :unpack_ipv4_addr
2046
-
2047
- #======================================#
2048
- #
2049
- #======================================#
2050
-
2051
-
2052
- #==============================================================================#
2053
- # unpack_ipv4_netmask()
2054
- #==============================================================================#
2055
-
2056
- # DEPRICATED - USE unpack_ip_netmask INSTEAD
2057
- # Unack a packed IPv4 netmask into a integer representing the number of
2058
- # bits in the CIDR mask. No attempt at validation is performed.
2059
- #
2060
- # - Arguments:
2061
- # * Byte-packed IPv4 netmask
2062
- #
2063
- # - Returns:
2064
- # * IPv4 netmask as number of bits (cidr format).
2065
- #
2066
- # Example:
2067
- # unpacked = IPAdmin.unpack_ipv4_netmask(packed)
2068
- #
2069
- def unpack_ipv4_netmask(packed_mask)
2070
- mask = 32
2071
- 32.times do
2072
- if ( (packed_mask & 1) != 0)
2073
- break
2074
- end
2075
- packed_mask = packed_mask >> 1
2076
- mask = mask - 1
2077
- end
2078
-
2079
- return(mask)
2080
- end
2081
- module_function :unpack_ipv4_netmask
2082
-
2083
- #======================================#
2084
- #
2085
- #======================================#
2086
-
2087
-
2088
- #==============================================================================#
2089
- # unpack_ipv6_addr()
2090
- #==============================================================================#
2091
-
2092
- # DEPRICATED - USE unpack_ip_addr INSTEAD
2093
- # Unack a packed IPv6 address back into a printable string. No attempt at
2094
- # validation is performed.
2095
- #
2096
- # - Arguments:
2097
- # * Byte-packed IPv6 address
2098
- #
2099
- # - Returns:
2100
- # * IPv6 address.
2101
- #
2102
- # Example:
2103
- # unpacked = IPAdmin.unpack_ipv6_addr(packed)
2104
- #
2105
- def unpack_ipv6_addr(packed_ip)
2106
- hex_fields = []
2107
- (0..7).each do |x|
2108
- hex_fields[x] = packed_ip & 0xFFFF
2109
- hex_fields[x] = (hex_fields[x]).to_s(16)
2110
- packed_ip = packed_ip >> 16
2111
-
2112
- # if hex_fields[x] < 4 characters, then pad with 0's
2113
- (4 - hex_fields[x].length).times do
2114
- hex_fields[x] = '0' << hex_fields[x]
2115
- end
2116
- end
2117
-
2118
- hex_fields.reverse!
2119
- ip = hex_fields.join(':')
2120
-
2121
- return(ip)
2122
- end
2123
- module_function :unpack_ipv6_addr
2124
-
2125
- #======================================#
2126
- #
2127
- #======================================#
2128
-
2129
-
2130
- #==============================================================================#
2131
- # unpack_ipv6_netmask()
2132
- #==============================================================================#
2133
-
2134
- # DEPRICATED - USE unpack_ip_netmask INSTEAD
2135
- # Unack a packed IPv6 netmask into a integer representing the number of
2136
- # bits in the CIDR mask. No attempt at validation is performed.
2137
- #
2138
- # - Arguments:
2139
- # * Byte-packed IPv6 netmask
2140
- #
2141
- # - Returns:
2142
- # * IPv6 netmask as number of bits (cidr format).
2143
- #
2144
- # Example:
2145
- # unpacked = IPAdmin.unpack_ipv6_netmask(packed)
2146
- #
2147
- def unpack_ipv6_netmask(packed_mask)
2148
-
2149
- mask = 128
2150
- 128.times do
2151
- if ( (packed_mask & 1) == 1)
2152
- break
2153
- end
2154
- mask = mask - 1
2155
- packed_mask = packed_mask >> 1
2156
- end
2157
-
2158
- return(mask)
2159
- end
2160
- module_function :unpack_ipv6_netmask
2161
-
2162
- #======================================#
2163
- #
2164
- #======================================#
2165
-
2166
- end # module IPAdmin
2167
1507
  __END__
2168
1508