This is an automated email from the git hooks/post-receive script. glondu pushed a commit to branch master in repository ocaml-ipaddr.
commit 35487fa6967374bc8eb01daa36de8b6ba3623942 Author: Stephane Glondu <st...@glondu.net> Date: Thu Jun 26 15:02:06 2014 +0200 Imported Upstream version 2.1.0 --- CHANGES | 8 +++- README.md | 3 +- _oasis | 2 +- lib/ipaddr.ml | 98 +++++++++++++++++++++++++++++++++++++++++++++---- lib/ipaddr.mli | 77 ++++++++++++++++++++++++++++++++++++-- lib_test/test_ipaddr.ml | 20 ++++++++++ 6 files changed, 194 insertions(+), 14 deletions(-) diff --git a/CHANGES b/CHANGES index 9c8831a..5a4e174 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,10 @@ -2.0.0 (trunk): +2.1.0 (2014-01-20): +* Add `of_string_raw` to `Ipaddr.V4.Prefix` and `Ipaddr.V6.Prefix` +* Add `of_addr` to `Ipaddr.V4.Prefix` and `Ipaddr.V6.Prefix` +* Add type `('v4,'v6) v4v6` to `Ipaddr` to represent version disjuncts +* Add `Ipaddr.Prefix` module for generic prefix manipulation + +2.0.0 (2014-01-17): * Change `Ipaddr.V4.make` to accept `int` rather than `int32` (breaking) * Add IPv6 support * Add generic IP address support diff --git a/README.md b/README.md index d32b368..9698e07 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ Features: * IPv4 and IPv6 [CIDR-scoped address](http://tools.ietf.org/html/rfc4291#section-2.3) support * `Ipaddr.V4` and `Ipaddr.V4.Prefix` modules are `Map.OrderedType` * `Ipaddr.V6` and `Ipaddr.V6.Prefix` modules are `Map.OrderedType` - * `Ipaddr` is a `Map.OrderedType` + * `Ipaddr` and `Ipaddr.Prefix` modules are `Map.OrderedType` * IP address scope classification + * IPv4-mapped addresses in IPv6 (::ffff:0:0/96) are an embedding of IPv4 * MAC-48 (Ethernet) address support * `Macaddr` is a `Map.OrderedType` diff --git a/_oasis b/_oasis index 2450b2c..285cafd 100644 --- a/_oasis +++ b/_oasis @@ -1,6 +1,6 @@ OASISFormat: 0.3 Name: ipaddr -Version: 2.0.0 +Version: 2.1.0 Synopsis: A library for manipulation of IP (and MAC) address representations Authors: David Sheets, Anil Madhavapeddy, Hugo Heuzard License: ISC diff --git a/lib/ipaddr.ml b/lib/ipaddr.ml index 7b06d19..8ade0bf 100644 --- a/lib/ipaddr.ml +++ b/lib/ipaddr.ml @@ -201,16 +201,24 @@ module V4 = struct (* string conversion *) - let _of_string_exn s = - let i = ref 0 in + let _of_string_raw s i = let quad = of_string_raw s i in expect_char s i '/'; let p = parse_dec_int s i in if p > 32 || p < 0 then raise (Parse_error ("invalid prefix size", s)); - expect_end s i; (p,quad) + let of_string_raw s i = + let (p,quad) = _of_string_raw s i in + make p quad + + let _of_string_exn s = + let i = ref 0 in + let res = _of_string_raw s i in + expect_end s i; + res + let of_string_exn s = let (p,quad) = _of_string_exn s in make p quad let of_string s = try Some (of_string_exn s) with _ -> None @@ -237,6 +245,8 @@ module V4 = struct let mem ip (pre,sz) = let host = 32 - sz in (ip >|> host) = (pre >|> host) + let of_addr ip = make 32 ip + let global = make 0 (ip 0 0 0 0) let relative = make 8 (ip 0 0 0 0) let loopback = make 8 (ip 127 0 0 0) @@ -566,16 +576,24 @@ module V6 = struct let network_address (pre,sz) addr = logor pre (logand addr (lognot (mask sz))) - let _of_string_exn s = - let i = ref 0 in + let _of_string_raw s i = let v6 = of_string_raw s i in expect_char s i '/'; let p = parse_dec_int s i in if p > 128 || p < 0 then raise (Parse_error ("invalid prefix size", s)); - expect_end s i; (p, v6) + let of_string_raw s i = + let (p,v6) = _of_string_raw s i in + make p v6 + + let _of_string_exn s = + let i = ref 0 in + let res = _of_string_raw s i in + expect_end s i; + res + let of_string_exn s = let (p,v6) = _of_string_exn s in make p v6 let of_string s = try Some (of_string_exn s) with _ -> None @@ -605,6 +623,8 @@ module V6 = struct let m = mask sz in logand ip m = logand pre m + let of_addr ip = make 128 ip + let global_unicast_001 = make 3 (ip 0x2000 0 0 0 0 0 0 0) let link = make 10 (ip 0xfe80 0 0 0 0 0 0 0) let unique_local = make 7 (ip 0xfc00 0 0 0 0 0 0 0) @@ -646,7 +666,8 @@ module V6 = struct let is_private i = (scope i) <> Global end -type t = V4 of V4.t | V6 of V6.t +type ('v4,'v6) v4v6 = V4 of 'v4 | V6 of 'v6 +type t = (V4.t,V6.t) v4v6 let compare a b = match a,b with | V4 a, V4 b -> V4.compare a b @@ -708,3 +729,66 @@ let is_multicast = function let is_private = function | V4 v4 -> V4.is_private v4 | V6 v6 -> V6.is_private v6 + +module Prefix = struct + module Addr = struct + let to_v6 = to_v6 + end + + type addr = t + type t = (V4.Prefix.t,V6.Prefix.t) v4v6 + + let compare a b = match a,b with + | V4 a , V4 b -> V4.Prefix.compare a b + | V6 a , V6 b -> V6.Prefix.compare a b + | V4 _ , V6 _ -> -1 + | V6 _ , V4 _ -> 1 + + let of_string_raw s offset = + let len = String.length s in + if len < !offset + 1 then raise (need_more s); + match s.[0] with + | '[' -> V6 (V6.Prefix.of_string_raw s offset) + | _ -> + let pos = !offset in + try V4 (V4.Prefix.of_string_raw s offset) + with Parse_error (v4_msg,_) -> + offset := pos; + try V6 (V6.Prefix.of_string_raw s offset) + with Parse_error(v6_msg,s) -> + let msg = Printf.sprintf + "not an IPv4 prefix: %s\nnot an IPv6 prefix: %s" + v4_msg v6_msg + in raise (Parse_error (msg,s)) + + let of_string_exn s = of_string_raw s (ref 0) + + let of_string s = try Some (of_string_exn s) with _ -> None + + let v6_of_v4 v4 = V6.Prefix.make + (96 + V4.Prefix.bits v4) + (v6_of_v4 (V4.Prefix.network v4)) + + let v4_of_v6 v6 = match v4_of_v6 (V6.Prefix.network v6) with + | Some v4 -> Some (V4.Prefix.make (V6.Prefix.bits v6 - 96) v4) + | None -> None + + let to_v4 = function V4 v4 -> Some v4 | V6 v6 -> v4_of_v6 v6 + + let to_v6 = function V4 v4 -> v6_of_v4 v4 | V6 v6 -> v6 + + let mem ip prefix = V6.Prefix.mem (Addr.to_v6 ip) (to_v6 prefix) + + let of_addr = function + | V4 p -> V4 (V4.Prefix.of_addr p) + | V6 p -> V6 (V6.Prefix.of_addr p) + + let to_string = function + | V4 p -> V4.Prefix.to_string p + | V6 p -> V6.Prefix.to_string p + + let to_buffer buf = function + | V4 p -> V4.Prefix.to_buffer buf p + | V6 p -> V6.Prefix.to_buffer buf p + +end diff --git a/lib/ipaddr.mli b/lib/ipaddr.mli index c5dddbf..f44eefc 100644 --- a/lib/ipaddr.mli +++ b/lib/ipaddr.mli @@ -148,6 +148,10 @@ module V4 : sig an exception. *) val of_string : string -> t option + (** Same as [of_string_exn] but takes as an extra argument the offset + into the string for reading. *) + val of_string_raw : string -> int ref -> t + (** [to_string prefix] is the CIDR notation string representation of [prefix], i.e. XXX.XX.X.XXX/XX. *) val to_string : t -> string @@ -176,6 +180,10 @@ module V4 : sig (** [mem ip subnet] checks whether [ip] is found within [subnet]. *) val mem : addr -> t -> bool + (** [of_addr ip] create a subnet composed of only one address, [ip]. + It is the same as [make 32 ip]. *) + val of_addr : addr -> t + (** The default route, all addresses in IPv4-space, 0.0.0.0/0. *) val global : t @@ -352,6 +360,10 @@ module V6 : sig an exception. *) val of_string : string -> t option + (** Same as [of_string_exn] but takes as an extra argument the offset + into the string for reading. *) + val of_string_raw : string -> int ref -> t + (** [to_string prefix] is the CIDR notation string representation of [prefix], i.e. XXX:XX:X::XXX/XX. *) val to_string : t -> string @@ -380,6 +392,10 @@ module V6 : sig (** [mem ip subnet] checks whether [ip] is found within [subnet]. *) val mem : addr -> t -> bool + (** [of_addr ip] create a subnet composed of only one address, [ip]. + It is the same as [make 128 ip]. *) + val of_addr : addr -> t + (** Global Unicast 001, 2000::/3. *) val global_unicast_001 : t @@ -427,8 +443,11 @@ module V6 : sig include Map.OrderedType with type t := t end +(** Type of either an IPv4 value or an IPv6 value *) +type ('v4,'v6) v4v6 = V4 of 'v4 | V6 of 'v6 + (** Type of any IP address *) -type t = V4 of V4.t | V6 of V6.t +type t = (V4.t,V6.t) v4v6 val compare : t -> t -> int @@ -452,9 +471,6 @@ val of_string : string -> t option the string for reading. *) val of_string_raw : string -> int ref -> t -(** [v6_of_v4 ipv4] is the IPv6 representation of the IPv4 address [ipv4]. *) -val v6_of_v4 : V4.t -> V6.t - (** [v4_of_v6 ipv6] is the IPv4 representation of the IPv6 address [ipv6]. If [ipv6] is not an IPv4-mapped address, None is returned. *) val v4_of_v6 : V6.t -> V4.t option @@ -462,6 +478,9 @@ val v4_of_v6 : V6.t -> V4.t option (** [to_v4 addr] is the IPv4 representation of [addr]. *) val to_v4 : t -> V4.t option +(** [v6_of_v4 ipv4] is the IPv6 representation of the IPv4 address [ipv4]. *) +val v6_of_v4 : V4.t -> V6.t + (** [to_v6 addr] is the IPv6 representation of [addr]. *) val to_v6 : t -> V6.t @@ -481,4 +500,54 @@ val is_multicast : t -> bool addresses a node. *) val is_private : t -> bool +module Prefix : sig + type addr = t + + (** Type of a internet protocol subnet *) + type t = (V4.Prefix.t, V6.Prefix.t) v4v6 + + val compare : t -> t -> int + + (** [of_string_exn cidr] is the subnet prefix represented by the CIDR + string, [cidr]. Raises [Parse_error] if [cidr] is not a valid + representation of a CIDR notation routing prefix. *) + val of_string_exn : string -> t + + (** Same as [of_string_exn] but returns an option type instead of raising + an exception. *) + val of_string : string -> t option + + (** Same as [of_string_exn] but takes as an extra argument the offset + into the string for reading. *) + val of_string_raw : string -> int ref -> t + + (** [v4_of_v6 ipv6] is the IPv4 representation of the IPv6 subnet [ipv6]. + If [ipv6] is not an IPv4-mapped subnet, None is returned. *) + val v4_of_v6 : V6.Prefix.t -> V4.Prefix.t option + + (** [to_v4 subnet] is the IPv4 representation of [subnet]. *) + val to_v4 : t -> V4.Prefix.t option + + (** [v6_of_v4 ipv4] is the IPv6 representation of the IPv4 subnet [ipv4]. *) + val v6_of_v4 : V4.Prefix.t -> V6.Prefix.t + + (** [to_v6 subnet] is the IPv6 representation of [subnet]. *) + val to_v6 : t -> V6.Prefix.t + + (** [mem ip subnet] checks whether [ip] is found within [subnet]. *) + val mem : addr -> t -> bool + + (** [of_addr ip] create a subnet composed of only one address, [ip].*) + val of_addr : addr -> t + + (** [to_string subnet] is the text string representation of [subnet]. *) + val to_string : t -> string + + (** [to_buffer buf subnet] writes the text string representation of [subnet] + into [buf]. *) + val to_buffer : Buffer.t -> t -> unit + + include Map.OrderedType with type t := t +end + include Map.OrderedType with type t := t diff --git a/lib_test/test_ipaddr.ml b/lib_test/test_ipaddr.ml index e705a76..b3ae637 100644 --- a/lib_test/test_ipaddr.ml +++ b/lib_test/test_ipaddr.ml @@ -549,10 +549,30 @@ let test_map () = assert_equal ~msg:"max" (M.max_binding m) (of_string_exn maxv6, "the greatest host v6") +let test_prefix_mem () = + let ip = of_string_exn in + let v4net = Prefix.v4_of_v6 in + let ships = [ + ip "192.168.0.1", V4 V4.Prefix.private_192, true; + ip "192.168.0.1", Prefix.of_string_exn "::ffff:0:0/96", true; + ip "192.168.0.1", Prefix.of_string_exn "::ffff:0:0/95", true; + ip "192.168.0.1", Prefix.of_string_exn "::ffff:0:0/97", false; + ip "192.168.0.1", Prefix.of_string_exn "::ffff:128.0.0.0/97", true; + ip "::ffff:10.0.0.1", V4 V4.Prefix.private_10, true; + ip "::fffe:10.0.0.1", V4 V4.Prefix.private_10, false; + ] in + List.iter (fun (addr,subnet,is_mem) -> + let msg = Printf.sprintf "%s is%s in %s" + (to_string addr) (if is_mem then "" else " not") (Prefix.to_string subnet) + in + assert_equal ~msg (Prefix.mem addr subnet) is_mem + ) ships + let suite = "Test Generic Addresses" >::: [ "string_raw_rt" >:: test_string_raw_rt; "string_raw_rt_bad" >:: test_string_raw_rt_bad; "map" >:: test_map; + "prefix_mem" >:: test_prefix_mem; ] ;; -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ocaml-maint/packages/ocaml-ipaddr.git _______________________________________________ Pkg-ocaml-maint-commits mailing list Pkg-ocaml-maint-commits@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-ocaml-maint-commits