ipadmin 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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