subnet_calc 0.2.3 → 0.2.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c6269772bdd1895f45f3d245d545d2f1f38c0c0b
4
- data.tar.gz: 4b7c062156c81833fb15752a8f0546d6f7490632
3
+ metadata.gz: bc90d91915916592cdf05424c9aee5f9448f2257
4
+ data.tar.gz: ed2a21fbea8a6836dbf688698e911ad1edc59484
5
5
  SHA512:
6
- metadata.gz: e89aa0d80d8cd8e5777375d601bbf6950ed8ffdf6bd8ed9965b2a2fcd9319136fa203cb0d84ecc6fb19f344a0fcc2f63c224da6309252d698f300ace9b1fb607
7
- data.tar.gz: 52a283f8937e9ff97c31429e1881e218afe95cf71b79a3db338b00d51d94ffd434c670c258ccb3146d53a7c5efa534a368eba1bfc06de7959d3f122a4e33900f
6
+ metadata.gz: 7e7a93085e84393136d93c27f85a583442e49f564125d479f9ef36bcda69b3280e7dfeefa5cfa3a5bc586825f8fc32053120f4e1d011867c2333db1633025d0d
7
+ data.tar.gz: a4aaab7e14df16e5a6c30a2a519c1ed343b27984e0240d0b21f8074278e88d360381b014b726e9adb61e185b061945c46309846ba2634152f6dfe659f2d2f511
checksums.yaml.gz.sig CHANGED
Binary file
data/lib/subnet_calc.rb CHANGED
@@ -161,6 +161,324 @@ class SubnetCalc
161
161
  first_ip = (ip + [subnets.first.first]).join('.')
162
162
  last_ip = (ip + [subnets.first.last]).join('.')
163
163
 
164
+ subnet_bits = (subnet_mask.split('.')[class_n]).to_i.to_s(2).count("1")
165
+
166
+ result = {
167
+ class_type: class_type.upcase,
168
+ magic_number: magic_number,
169
+ hosts: hosts_per_subnet - 2,
170
+ subnet_mask: subnet_mask,
171
+ subnet_bitmask: subnet_mask.split('.').map \
172
+ {|x| ('0' * 7 + x.to_i.to_s(2))[-8..-1]},
173
+ prefix: prefix,
174
+ subnets: subnets,
175
+ range: "%s-%s" % [first_ip, last_ip],
176
+ subnet_bits: subnet_bits,
177
+ max_subnets: 2 ** (subnet_bits)
178
+ }
179
+
180
+ @octet_n = octet_n
181
+ @h = result
182
+ end
183
+
184
+
185
+ def to_s()
186
+
187
+ tfo = TableFormatter.new
188
+
189
+ tfo.source = @h[:subnets].map.with_index do |x,i|
190
+ ([i+1] + x.to_h.values).map(&:to_s)
191
+ end
192
+
193
+ tfo.labels = %w(index Network 1st last broadcast)
194
+ full_subnets_table = tfo.display(markdown: true).to_s
195
+
196
+ subnets_table = if full_subnets_table.lines.length > 14 then
197
+ (full_subnets_table.lines[0..13] + ["\n ... "]).join
198
+ else
199
+ full_subnets_table
200
+ end
201
+
202
+ # octet broken down
203
+
204
+ tfo2 = TableFormatter.new
205
+
206
+ prefixes = @prefixes[@octet_n].map {|x| '/' + x.to_s}
207
+ tfo2.source = [@h[:subnet_bitmask][@octet_n].chars, prefixes]
208
+ tfo2.labels = 8.times.map {|n| (2 ** n).to_s }.reverse
209
+ octet_table = tfo2.display(markdown: true).to_s
210
+
211
+ <<EOF
212
+
213
+
214
+ Subnet calculator
215
+ =================
216
+
217
+ Inputs:
218
+
219
+ #{Kvx.new(@inputs).to_s.lines.map {|x| ' ' * 2 + x}.join}
220
+
221
+ Summary
222
+ -------
223
+
224
+ * Network class: #{@h[:class_type]}
225
+ * magic number: #{@h[:magic_number]}
226
+ * hosts per subnet: #{@h[:hosts]}
227
+ * subnet mask: #{@h[:subnet_mask]}
228
+ * subnet bitmask: #{@h[:subnet_bitmask].join('.')}
229
+ * prefix bit-length: #{@h[:prefix]}
230
+ * range: #{@h[:range]}
231
+
232
+ * subnet_bits: #{@h[:subnet_bits]}
233
+ * maximum subnets: #{@h[:max_subnets]}
234
+
235
+
236
+
237
+ Breakdown
238
+ ---------
239
+
240
+ #{(@octet_n + 1).ordinal} octet:
241
+
242
+ #{indent octet_table}
243
+
244
+ ### Subnets
245
+
246
+
247
+ #{indent subnets_table}
248
+
249
+ -----------------------------------------------
250
+
251
+ EOF
252
+
253
+ end
254
+
255
+ def to_h()
256
+ @h
257
+ end
258
+
259
+ private
260
+
261
+ def class_subnets(n, block_size)
262
+
263
+ i = 0
264
+
265
+ subnets = n.times.inject([]) do |r,n|
266
+
267
+ broadcast = i + block_size - 1
268
+ first = i + 1
269
+ last = broadcast - 1
270
+
271
+ h = if block_given? then
272
+ yield(i,first,last,broadcast)
273
+ else
274
+ { network: i, first: first, last: last, broadcast: broadcast }
275
+ end
276
+ i += block_size
277
+
278
+ r << OpenStruct.new(h)
279
+
280
+ end
281
+
282
+ end
283
+
284
+ def class_b_subnets(n, block_size)
285
+
286
+ class_subnets(n, block_size) do |network, first, last, broadcast|
287
+
288
+ {
289
+ network: [network, 0].join('.'),
290
+ first: [network, 1].join('.'),
291
+ last: [broadcast, 254].join('.'),
292
+ broadcast: [broadcast, 255].join('.')
293
+ }
294
+
295
+ end
296
+
297
+ end
298
+
299
+ def class_a_subnets(n, block_size)
300
+
301
+ class_subnets(n, block_size) do |network, first, last, broadcast|
302
+
303
+ {
304
+ network: [network, 0, 0].join('.'),
305
+ first: [network, 1, 1].join('.'),
306
+ last: [broadcast, 255, 254].join('.'),
307
+ broadcast: [broadcast, 255, 255].join('.')
308
+ }
309
+
310
+ end
311
+
312
+ end
313
+
314
+ def indent(s, i=2)
315
+ s.lines.map{|x| ' ' * i + x}.join
316
+ end
317
+ end#!/usr/bin/env ruby
318
+
319
+ # file: subnet_calc.rb
320
+
321
+
322
+ require 'kvx'
323
+ require 'ostruct'
324
+ require 'table-formatter'
325
+
326
+
327
+ module Ordinals
328
+
329
+ refine Fixnum do
330
+ def ordinal
331
+ self.to_s + ( (10...20).include?(self) ? 'th' :
332
+ %w{ th st nd rd th th th th th th }[self % 10] )
333
+ end
334
+ end
335
+ end
336
+
337
+ class SubnetCalc
338
+
339
+ using Ordinals
340
+
341
+ attr_reader :to_h, :octets
342
+
343
+ def initialize(inputs={})
344
+
345
+ @inputs = inputs
346
+ default_inputs = {hosts: nil, ip: '192.168.0.0', prefix: nil}.merge(inputs)
347
+
348
+ # Using the input(s) supplied:
349
+
350
+ hosts, prefix = %i(hosts prefix).map {|x| default_inputs[x]}
351
+
352
+
353
+ @prefixes = 1.upto(32).each_slice(8).to_a
354
+
355
+ =begin
356
+ #=> [
357
+ [1, 2, 3, 4, 5, 6, 7, 8], [9, 10, 11, 12, 13, 14, 15, 16],
358
+ [17, 18, 19, 20, 21, 22, 23, 24], [25, 26, 27, 28, 29, 30, 31, 32]
359
+ ]
360
+ =end
361
+
362
+
363
+ octets = @prefixes.map.with_index do |octet, j|
364
+
365
+ a = octet.map.with_index do |prefix, i|
366
+
367
+ decimal = 2 ** (octet.length - 1 - i )
368
+
369
+ h = {
370
+ prefix: prefix,
371
+ decimal: decimal,
372
+ hosts_per_subnet: (2 ** 8) ** (@prefixes.length - 1 - j) * decimal
373
+ }
374
+
375
+ OpenStruct.new h
376
+
377
+ end
378
+
379
+ OpenStruct.new mask: nil, bits: a
380
+
381
+ end
382
+
383
+ @octets = octets
384
+
385
+
386
+ # ------------------------------------
387
+
388
+
389
+ octet_n, col, class_type = if hosts then
390
+
391
+ hosts_per_subnet = octets.flat_map.with_index do |octet,i|
392
+ octet.bits.map.with_index {|y,j| [i, j, y.hosts_per_subnet] }
393
+ end
394
+
395
+ # find the smallest decimal value to match the
396
+ # required number of hosts on a network
397
+
398
+ *r, _ = hosts_per_subnet.reverse.detect {|x| x.last > hosts + 1}
399
+
400
+ network = case hosts
401
+ when 1..254
402
+ 'c'
403
+ when 255..65534
404
+ 'b'
405
+ else
406
+ 'a'
407
+ end
408
+
409
+ (r + [network])
410
+
411
+ elsif prefix
412
+
413
+ prefixes = @prefixes.flat_map.with_index do |octet,i|
414
+ octet.map.with_index {|x,j| [i, j, x]}
415
+ end
416
+
417
+ *r, _ = prefixes.detect {|x| x.last == prefix}
418
+
419
+ network = case prefix
420
+ when 24..32
421
+ 'c'
422
+ when 16..23
423
+ 'b'
424
+ else
425
+ 'a'
426
+ end
427
+
428
+ (r + [network])
429
+ end
430
+
431
+
432
+ # Identify the network bits and the host bits
433
+
434
+ classes = ('a'..'d')
435
+
436
+ # identify the initial network bits for a class *a,b or c*
437
+
438
+ class_n = (classes.to_a.index(class_type) + 1)
439
+
440
+ network_bits = class_n.times.map {|x| Array.new(8, 1)}
441
+ host_bits = (classes.to_a.length - class_n).times.map {|x| Array.new(8, 0)}
442
+ address_bits = network_bits + host_bits
443
+
444
+ # add the mask to each octet
445
+
446
+ octets.each.with_index do |octet, i|
447
+ octet.mask = address_bits[i].join.to_i(2)
448
+ end
449
+
450
+
451
+ bit = octets[octet_n].bits[col]
452
+
453
+ magic_number, hosts_per_subnet, prefix = bit.decimal,
454
+ bit.hosts_per_subnet, bit.prefix
455
+
456
+ no_of_subnets = (2 ** 8.0) / bit.hosts_per_subnet
457
+
458
+ segments = (no_of_subnets >= 1 ? no_of_subnets : (1 / no_of_subnets)).to_i
459
+ n = col
460
+
461
+ # add the new mask to the octet
462
+
463
+ octets[octet_n].mask = octets[octet_n].bits.map(&:decimal)[0..n].inject(:+)
464
+ subnet_mask = octets.map(&:mask).join('.')
465
+
466
+ subnets = case class_type
467
+ when 'c'
468
+ class_subnets(segments, hosts_per_subnet)
469
+ when 'b'
470
+ class_b_subnets(256 / segments, bit.decimal)
471
+ when 'a'
472
+ class_a_subnets(256 ** 2 / segments, bit.decimal)
473
+ end
474
+
475
+ ip = (default_inputs[:ip] + ' ') .split('.')[0..octet_n-1]
476
+
477
+ first_ip = (ip + [subnets.first.first]).join('.')
478
+ last_ip = (ip + [subnets.first.last]).join('.')
479
+
480
+ subnet_bits = (subnet_mask.split('.')[class_n]).to_i.to_s(2).count("1")
481
+
164
482
  result = {
165
483
  class_type: class_type.upcase,
166
484
  magic_number: magic_number,
@@ -171,8 +489,8 @@ class SubnetCalc
171
489
  prefix: prefix,
172
490
  subnets: subnets,
173
491
  range: "%s-%s" % [first_ip, last_ip],
174
- subnet_bits: n+1,
175
- max_subnets: segments
492
+ subnet_bits: subnet_bits,
493
+ max_subnets: 2 ** (subnet_bits)
176
494
  }
177
495
 
178
496
  @octet_n = octet_n
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: subnet_calc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Robertson
metadata.gz.sig CHANGED
Binary file