class Subnets::Net6

Public Class Methods

new(p1, p2) click to toggle source
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(p1) click to toggle source

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.

@param [String] s @return {Net6} @raise {Subnets::ParseError}

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(p1 = v1, p2 = {}) click to toggle source

@overload random(rand=Random.new, opts={})

@param rand [#rand] (optional) a random number generator
@param opts [Hash]
@option opts [Boolean] :zeros include a random string of zeros at a random position rather than simply randomizing the entire address

@return [Net6] a random Net6

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(p1) click to toggle source

@return [Subnets::Net6] the smallest subnet that includes all of the subnets in nets

@param nets [Array<Subnets::Net6>]

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);
}

Public Instance Methods

==(p1) click to toggle source

@return [Boolean]

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;
}
Also aliased as: eql?
===(p1)

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.

@param [String, IP, Net] v

Alias for: include?
address() click to toggle source
VALUE
method_net6_address(VALUE self) {
  net6_t *net;
  Data_Get_Struct(self, net6_t, net);
  return ip6_new(IP6, net->address);
}
eql?(p1)

@return [Boolean]

Alias for: ==
hash() click to toggle source

@return [Integer]

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;
}
hextets() click to toggle source

(see Subnets::IP6#hextets)

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?(p1) click to toggle source

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.

@param [String, IP, Net] v

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;
}
Also aliased as: ===
mask() click to toggle source
VALUE
method_net6_mask(VALUE self) {
  net6_t *net;
  Data_Get_Struct(self, net6_t, net);
  return ip6_new(IP6, net->mask);
}
prefixlen() click to toggle source

(see Subnets::Net4#prefixlen)

VALUE
method_net6_prefixlen(VALUE self) {
  net6_t *net;
  Data_Get_Struct(self, net6_t, net);
  return INT2FIX(net->prefixlen);
}
to_s() click to toggle source

Return a String in CIDR notation.

@return [String]

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);
}