Class: Subnets::Net6

Inherits:
Net
  • Object
show all
Defined in:
ext/subnets/ext.c

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Net

#inspect

Class Method Details

.new(hextets, prefixlen) ⇒ Object



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'ext/subnets/ext.c', line 113

VALUE
method_net6_new(VALUE class, VALUE hextets, VALUE prefixlen) {
  net6_t net;

  if (RARRAY_LEN(hextets) != 8) {
    rb_raise(rb_eArgError, "hextets must be size=8, was %ld", RARRAY_LEN(hextets));
  }

  for (ssize_t i = 0; i < RARRAY_LEN(hextets); i++) {
    net.address.x[i] = NUM2INT(RARRAY_AREF(hextets, i)) & 0xffff;
  }

  net.prefixlen = NUM2INT(prefixlen);
  if (!(net.prefixlen >= 0 && net.prefixlen <= 128)) {
    rb_raise(rb_eArgError, "prefixlen must be in range [0,128], was %d", net.prefixlen);
  }

  net.mask = mk_mask6(net.prefixlen);

  return net6_new(class, net);
}

.parse(s) ⇒ Net6

Parse s as an IPv6 network in CIDR notation. Handles the following formats:

  • x:x:x:x:x:x:x:x consisting of eight hexadecimal numbers of one to four digits (16 bits) separated by colons

  • x:x:x::x:x:x as above, but a single double-colon replaces two or more repeated zeros

  • x:x:x:x:x:x:d.d.d.d consisting of a colon-separated hexadecimal portion as above defining up to six hextets, followed by dot-separated decimal numbers 0-255 in typical IPv4 format.

Parameters:

  • s (String)

Returns:

Raises:



171
172
173
174
175
176
177
178
179
180
# File 'ext/subnets/ext.c', line 171

VALUE
method_net6_parse(VALUE class, VALUE s) {
  const char *buf = StringValueCStr(s);

  net6_t net;
  if (!read_net6_strict(buf, &net)) {
    raise_parse_error("net6", buf);
  }
  return net6_new(class, net);
}

.random(rand = Random.new, opts = {}) ⇒ Net6

Returns a random Net6.

Parameters:

  • rand (#rand) (defaults to: Random.new)

    (optional) a random number generator

  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • :zeros (Boolean)

    include a random string of zeros at a random position rather than simply randomizing the entire address

Returns:

  • (Net6)

    a random Net6



283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'ext/subnets/ext.c', line 283

VALUE
method_net6_random(int argc, VALUE *argv, VALUE class) {
  net6_t net;
  VALUE rng;
  VALUE opts;

  rb_scan_args(argc, argv, "01:", &rng, &opts);
  ip6_fill_random(&net.address, rng, opts);
  net.prefixlen = FIX2INT(rb_funcall(rng, rb_intern("rand"), 1, INT2FIX(128+1)));
  net.mask = mk_mask6(net.prefixlen);

  return net6_new(class, net);
}

.summarize(nets) ⇒ Subnets::Net6

the subnets in nets

Parameters:

Returns:



865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
# File 'ext/subnets/ext.c', line 865

VALUE
method_net6_summarize(VALUE class, VALUE nets) {
  net6_t result;

  for (ssize_t i = 0; i < RARRAY_LEN(nets); i++) {
    net6_t *net;
    VALUE rbnet = RARRAY_AREF(nets, i);

    assert_kind_of(rbnet, Net6);

    Data_Get_Struct(rbnet, net6_t, net);

    if (i == 0) {
      result.address = ip6_band(net->address, net->mask);
      result.prefixlen = net->prefixlen;
      result.mask = net->mask;
    } else {
      while(result.prefixlen > net->prefixlen ||
            !ip6_eql_p(result.address, ip6_band(net->address, result.mask))) {
        result.prefixlen = MIN(result.prefixlen-1, net->prefixlen);
        result.mask = mk_mask6(result.prefixlen);
        result.address = ip6_band(result.address, result.mask);
      }
    }
  }

  return net6_new(class, result);
}

Instance Method Details

#==(other) ⇒ Boolean Also known as: eql?

Returns:

  • (Boolean)


679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
# File 'ext/subnets/ext.c', line 679

VALUE
method_net6_eql_p(VALUE self, VALUE other) {
  net6_t *a, *b;

  if (CLASS_OF(other) != CLASS_OF(self)) {
    return Qfalse;
  }

  Data_Get_Struct(self, net6_t, a);
  Data_Get_Struct(other, net6_t, b);

  if (a->prefixlen != b->prefixlen) {
    return Qfalse;
  }

  for (int i=0; i<8; i++) {
    if (a->address.x[i] != b->address.x[i]) return Qfalse;
  }
  return Qtrue;
}

#addressObject



769
770
771
772
773
774
# File 'ext/subnets/ext.c', line 769

VALUE
method_net6_address(VALUE self) {
  net6_t *net;
  Data_Get_Struct(self, net6_t, net);
  return ip6_new(IP6, net->address);
}

#hashInteger

Returns:

  • (Integer)


740
741
742
743
744
745
746
747
748
749
750
751
752
# File 'ext/subnets/ext.c', line 740

VALUE
method_net6_hash(VALUE self) {
  net6_t *net;
  VALUE ret;

  Data_Get_Struct(self, net6_t, net);

  ret = hash(INT2FIX(net->prefixlen));
  for (int i=0; i<8; i++) {
    ret = xor(ret, hash(INT2FIX(net->address.x[i])));
  }
  return ret;
}

#hextetsArray<Fixnum>

Returns 16-bit hextets, most significant first.

Returns:

  • (Array<Fixnum>)

    16-bit hextets, most significant first



810
811
812
813
814
815
816
817
818
819
820
821
822
# File 'ext/subnets/ext.c', line 810

VALUE
method_net6_hextets(VALUE self) {
  net6_t *net;
  VALUE hextets;

  Data_Get_Struct(self, net6_t, net);

  hextets = rb_ary_new();
  for (int i=0; i<8; i++) {
    rb_ary_push(hextets, INT2FIX(net->address.x[i]));
  }
  return hextets;
}

#include?(v) ⇒ Boolean Also known as: ===

Test if this network includes v.

A String must parse as an IP6 or Net6. An IP6 must be included within the range defined by this network. A Net6 must both have a prefixlen greater than or equal to that of this network, and have an address included within the range defined by this network.

Parameters:

Returns:

  • (Boolean)


488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
# File 'ext/subnets/ext.c', line 488

VALUE
method_net6_include_p(VALUE self, VALUE v) {
  net6_t *net;
  Data_Get_Struct(self, net6_t, net);

  if (CLASS_OF(v) == IP6) {
    ip6_t *ip;
    Data_Get_Struct(v, ip6_t, ip);
    return net6_include_p(*net, *ip) ? Qtrue : Qfalse;
  } else if (CLASS_OF(v) == Net6) {
    net6_t *other;
    Data_Get_Struct(v, net6_t, other);
    return net6_include_net6_p(*net, *other) ? Qtrue : Qfalse;
  } else if (CLASS_OF(v) == IP4 || CLASS_OF(v) == Net4) {
    return Qfalse;
  } else if (rb_obj_is_kind_of(v, rb_cString)) {
    const char *buf = StringValueCStr(v);

    {
      net6_t other;
      if (read_net6_strict(buf, &other)) {
        return net6_include_net6_p(*net, other) ? Qtrue : Qfalse;
      }
    }
    {
      ip6_t ip;
      if (read_ip6_strict(buf, &ip)) {
        return net6_include_p(*net, ip) ? Qtrue : Qfalse;
      }
    }
  }

  return Qfalse;
}

#maskObject



783
784
785
786
787
788
# File 'ext/subnets/ext.c', line 783

VALUE
method_net6_mask(VALUE self) {
  net6_t *net;
  Data_Get_Struct(self, net6_t, net);
  return ip6_new(IP6, net->mask);
}

#prefixlenFixnum

The prefix length of this network, or number of leading ones in the netmask.

Returns:

  • (Fixnum)


426
427
428
429
430
431
# File 'ext/subnets/ext.c', line 426

VALUE
method_net6_prefixlen(VALUE self) {
  net6_t *net;
  Data_Get_Struct(self, net6_t, net);
  return INT2FIX(net->prefixlen);
}

#to_sString

Return a String in CIDR notation.

Returns:

  • (String)


574
575
576
577
578
579
580
581
582
# File 'ext/subnets/ext.c', line 574

VALUE
method_net6_to_s(VALUE self) {
  net6_t *net;
  char buf[64];

  Data_Get_Struct(self, net6_t, net);
  net6_snprint(*net, buf, 64);
  return rb_str_new2(buf);
}