This commit is contained in:
swrup 2025-11-11 02:07:51 +01:00
parent aa2ff7b2f0
commit 2f3113f55d
11742 changed files with 1223940 additions and 0 deletions

View file

@ -0,0 +1,56 @@
(library
(name ipaddr)
(public_name ipaddr)
(modules ipaddr)
(libraries macaddr domain-name))
(library
(name macaddr)
(public_name macaddr)
(modules macaddr))
(library
(name ipaddr_sexp)
(public_name ipaddr-sexp)
(modules ipaddr_sexp)
(preprocess
(pps ppx_sexp_conv))
(libraries ipaddr sexplib0))
(library
(name macaddr_sexp)
(public_name macaddr-sexp)
(modules macaddr_sexp)
(preprocess
(pps ppx_sexp_conv))
(libraries macaddr sexplib0))
(library
(name ipaddr_unix)
(public_name ipaddr.unix)
(modules ipaddr_unix)
(libraries unix ipaddr))
(library
(name ipaddr_cstruct)
(public_name ipaddr-cstruct)
(modules ipaddr_cstruct)
(libraries ipaddr cstruct))
(library
(name macaddr_cstruct)
(public_name macaddr-cstruct)
(modules macaddr_cstruct)
(libraries macaddr cstruct))
(library
(name ipaddr_top)
(public_name ipaddr.top)
(modules ipaddr_top)
(libraries macaddr.top ipaddr compiler-libs))
(library
(name macaddr_top)
(public_name macaddr.top)
(modules macaddr_top)
(libraries macaddr compiler-libs))

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,811 @@
(*
* Copyright (c) 2019 Anil Madhavapeddy <anil@recoil.org>
* Copyright (c) 2013-2015 David Sheets <sheets@alum.mit.edu>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*)
(** A library for manipulation of IP address representations.
{e v5.6.1 - {{:https://github.com/mirage/ocaml-ipaddr} homepage}} *)
exception Parse_error of string * string
(** [Parse_error (err,packet)] is raised when parsing of the IP address syntax
fails. [err] contains a human-readable error and [packet] is the original
octet list that failed to parse. *)
(** Type of ordered address scope classifications *)
type scope = Point | Interface | Link | Admin | Site | Organization | Global
val string_of_scope : scope -> string
(** [string_of_scope scope] returns a human-readable representation of {!scope}. *)
val scope_of_string : string -> (scope, [> `Msg of string ]) result
(** [scope_of_string s] returns a {!scope} from a string representation of [s].
Valid string values for [s] can be obtained via {!string_of_scope}. *)
val pp_scope : Format.formatter -> scope -> unit
[@@ocaml.toplevel_printer]
(** [pp_scope fmt scope] outputs a human-readable representation of {!scope} to
the [fmt] formatter. *)
(** A collection of functions for IPv4 addresses. *)
module V4 : sig
type t
(** Type of the internet protocol v4 address of a host *)
val make : int -> int -> int -> int -> t
(** Converts the low bytes of four int values into an abstract {!V4.t}. *)
(** {3 Text string conversion}
These manipulate human-readable IPv4 addresses (for example
[192.168.1.2]). *)
val of_string : string -> (t, [> `Msg of string ]) result
(** [of_string s] is the address {!t} represented by the human-readable IPv4
address [s]. Returns a human-readable error string if parsing failed. *)
val of_string_exn : string -> t
(** [of_string_exn s] is the address {!t} represented as a human-readable IPv4
address [s]. Raises {!Parse_error} if [s] is invalid or truncated. *)
val of_string_raw : string -> int ref -> t
(** [of_string_raw s off] acts as {!of_string_exn} but takes as an extra
argument the offset into the string for reading. [off] will be mutated to
an unspecified value during the function call. [s] will a {!Parse_error}
exception if it is an invalid or truncated IP address. *)
val with_port_of_string :
default:int -> string -> (t * int, [> `Msg of string ]) result
(** [with_port_of_string ~default s] is the address {!t} represented by the
human-readble IPv4 address [s] with a possibly port [:<port>] (otherwise,
we take the [default] value). *)
val to_string : t -> string
(** [to_string ipv4] is the dotted decimal string representation of [ipv4],
i.e. [XXX.XX.X.XXX]. *)
val to_buffer : Buffer.t -> t -> unit
(** [to_buffer buf ipv4] writes the string representation of [ipv4] into the
buffer [buf]. *)
val pp : Format.formatter -> t -> unit
[@@ocaml.toplevel_printer]
(** [pp f ipv4] outputs a human-readable representation of [ipv4] to the
formatter [f]. *)
(** {3 Octets conversion}
These manipulate IPv4 addresses represented as a sequence of four bytes.
(e.g for example [0xc0a80102] will be the representation of the
human-readable [192.168.1.2] address. *)
val of_octets : ?off:int -> string -> (t, [> `Msg of string ]) result
(** [of_octets ?off s] is the IPv4 address {!t} represented by the octets in
[s] starting from offset [off] within the string. Returns a human-readable
error string if [s] is not at least [off+4] bytes long. [off] defaults to
0. *)
val of_octets_exn : ?off:int -> string -> t
(** [of_octets_exn ipv4_octets] is the IPv4 address represented by
[ipv4_octets] starting from offset [off]. Raises {!Parse_error} if
[ipv4_octets] is not at least [off+4] bytes long. [off] defaults to 0. *)
val write_octets :
?off:int -> t -> bytes -> (unit, [> `Msg of string ]) result
(** [write_octets ?off ipv4 b] writes the [ipv4] as octets to [b] starting
from offset [off]. [b] must be at least [off+4] long or an error is
returned. *)
val write_octets_exn : ?off:int -> t -> bytes -> unit
(** [write_octets_exn ?off ipv4 b] writes the [ipv4] as octets to [b] starting
from offset [off]. [b] must be at least [off+4] long or a {!Parse_error}
is raised. *)
val to_octets : t -> string
(** [to_octets ipv4] returns the 4 bytes representing the [ipv4] octets. *)
(** {3 Int conversion} *)
val of_int32 : int32 -> t
(** [of_int32 ipv4_packed] is the address represented by [ipv4_packed]. *)
val to_int32 : t -> int32
(** [to_int32 ipv4] is the 32-bit packed encoding of [ipv4]. *)
val of_int16 : int * int -> t
(** [of_int16 ipv4_packed] is the address represented by [ipv4_packed]. *)
val to_int16 : t -> int * int
(** [to_int16 ipv4] is the 16-bit packed encoding of [ipv4]. *)
(** {3 MAC conversion} *)
val multicast_to_mac : t -> Macaddr.t
(** [multicast_to_mac ipv4] is the MAC address corresponding to the multicast
address [ipv4]. Described by
{{:http://tools.ietf.org/html/rfc1112#section-6.2} RFC 1112}. *)
(** {3 Host conversion} *)
val to_domain_name : t -> [ `host ] Domain_name.t
(** [to_domain_name ipv4] is the domain name label list for reverse lookups of
[ipv4]. This includes the [.in-addr.arpa] suffix. *)
val of_domain_name : 'a Domain_name.t -> t option
(** [of_domain_name name] is [Some t] if the [name] has an [.in-addr.arpa]
suffix, and an IPv4 address prefixed. *)
(** {3 Utility functions} *)
val succ : t -> (t, [> `Msg of string ]) result
(** [succ ipv4] is ip address next to [ipv4]. Returns a human-readable error
string if it's already the highest address. *)
val pred : t -> (t, [> `Msg of string ]) result
(** [pred ipv4] is ip address before [ipv4]. Returns a human-readable error
string if it's already the lowest address. *)
(** {3 Common addresses} *)
val any : t
(** [any] is 0.0.0.0. *)
val unspecified : t
(** [unspecified] is 0.0.0.0. *)
val broadcast : t
(** [broadcast] is 255.255.255.255. *)
val nodes : t
(** [nodes] is 224.0.0.1. *)
val routers : t
(** [routers] is 224.0.0.2. *)
val localhost : t
(** [localhost] is 127.0.0.1. *)
(** A module for manipulating IPv4 network prefixes (CIDR). *)
module Prefix : sig
type addr = t
type t
(** Type of a internet protocol subnet: an address and prefix length. *)
val mask : int -> addr
(** [mask n] is the pseudo-address of an [n] bit subnet mask. *)
val make : int -> addr -> t
(** [make n addr] is the cidr of [addr] with [n] bits prefix. *)
val prefix : t -> t
(** [prefix cidr] is the subnet prefix of [cidr] where all non-prefix bits
set to 0. *)
val network_address : t -> addr -> addr
(** [network_address cidr addr] is the address with prefix [cidr] and suffix
from [addr]. See <http://tools.ietf.org/html/rfc4291#section-2.3>. *)
val of_string : string -> (t, [> `Msg of string ]) result
(** [of_string cidr] is the subnet prefix represented by the CIDR string,
[cidr]. Returns a human-readable parsing error message if [cidr] is not
a valid representation of a CIDR notation routing prefix. *)
val of_string_exn : string -> t
(** [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_raw : string -> int ref -> t
(** Same as {!of_string_exn} but takes as an extra argument the offset into
the string for reading. *)
val to_string : t -> string
(** [to_string cidr] is the CIDR notation string representation of [cidr],
i.e. [XXX.XX.X.XXX/XX]. *)
val pp : Format.formatter -> t -> unit
[@@ocaml.toplevel_printer]
(** [pp f cidr] outputs a human-readable representation of [cidr] to the
formatter [f]. *)
val to_buffer : Buffer.t -> t -> unit
(** [to_buffer buf cidr] writes the string representation of [cidr] into the
buffer [buf]. *)
val of_netmask_exn : netmask:addr -> address:addr -> t
(** [of_netmask_exn ~netmask ~address] is the subnet prefix of [address]
with netmask [netmask]. *)
val of_netmask :
netmask:addr -> address:addr -> (t, [> `Msg of string ]) result
(** [of_netmask ~netmask ~address] is the cidr of [address] with netmask
[netmask]. *)
val mem : addr -> t -> bool
(** [mem ip subnet] checks whether [ip] is found within [subnet]. *)
val subset : subnet:t -> network:t -> bool
(** [subset ~subnet ~network] checks whether [subnet] is contained within
[network]. *)
val of_addr : addr -> t
(** [of_addr ip] create a subnet composed of only one address, [ip]. It is
the same as [make 32 ip]. *)
val global : t
(** The default route, all addresses in IPv4-space, 0.0.0.0/0. *)
val loopback : t
(** The host loopback network, 127.0.0.0/8. *)
val link : t
(** The local-link network, 169.254.0.0/16. *)
val relative : t
(** The relative addressing network, 0.0.0.0/8. *)
val multicast : t
(** The multicast network, 224.0.0.0/4. *)
val private_10 : t
(** The private subnet with 10 as first octet, 10.0.0.0/8. *)
val private_172 : t
(** The private subnet with 172 as first octet, 172.16.0.0/12. *)
val private_192 : t
(** The private subnet with 192 as first octet, 192.168.0.0/16. *)
val private_blocks : t list
(** The privately addressable networks: [loopback], [link], [private_10],
[private_172], [private_192]. *)
val broadcast : t -> addr
(** [broadcast subnet] is the broadcast address for [subnet]. *)
val network : t -> addr
(** [network subnet] is the address for [subnet]. *)
val netmask : t -> addr
(** [netmask subnet] is the netmask for [subnet]. *)
val address : t -> addr
(** [address cidr] is the address for [cidr]. *)
val bits : t -> int
(** [bits cidr] is the bit size of the [cidr] prefix. *)
val first : t -> addr
(** [first cidr] is first valid unicast address in this [cidr]. *)
val last : t -> addr
(** [last cidr] is last valid unicast address in this [cidr]. *)
val hosts : ?usable:bool -> t -> addr Seq.t
(** [hosts cidr] is the sequence of host addresses in this [cidr]. By
default, network and broadcast addresses are omitted. This can be
changed by setting [usable] to false. *)
val subnets : int -> t -> t Seq.t
(** [subnets n cidr] is the sequence of subnets of [cidr] with a prefix
length of [n]. *)
include Map.OrderedType with type t := t
end
val scope : t -> scope
(** [scope ipv4] is the classification of [ipv4] by the {!scope} hierarchy. *)
val is_global : t -> bool
(** [is_global ipv4] is a predicate indicating whether [ipv4] globally
addresses a node. *)
val is_multicast : t -> bool
(** [is_multicast ipv4] is a predicate indicating whether [ipv4] is a
multicast address. *)
val is_private : t -> bool
(** [is_private ipv4] is a predicate indicating whether [ipv4] privately
addresses a node. *)
include Map.OrderedType with type t := t
module Set : Set.S with type elt := t
module Map : Map.S with type key := t
end
(** A collection of functions for IPv6 addresses. *)
module V6 : sig
type t
(** Type of the internet protocol v6 address of a host *)
val make : int -> int -> int -> int -> int -> int -> int -> int -> t
(** Converts the low bytes of eight int values into an abstract {!V6.t}. *)
(** {3 Text string conversion} *)
val of_string : string -> (t, [> `Msg of string ]) result
(** [of_string ipv6_string] is the address represented by the human-readable
IPv6 address [ipv6_string]. Returns a human-readable error string if
parsing failed. *)
val of_string_exn : string -> t
(** [of_string_exn ipv6_string] is the address represented by the
human-readable IPv6 address [ipv6_string]. Raises {!Parse_error} if
[ipv6_string] is invalid or truncated. *)
val with_port_of_string :
default:int -> string -> (t * int, [> `Msg of string ]) result
(** [with_port_of_string ~default ipv6_string] is the address represented by
[ipv6_string] with a possibly [:<port>] (otherwise, we take the [default]
value). Due to the [':'] separator, the user should expand [ipv6_string]
to let us to consider the last [:<port>] as a port. In other words:
- [::1:8080] returns the IPv6 [::1:8080] with the [default] port
- [0:0:0:0:0:0:0:1:8080] returns [::1] with the port [8080]. *)
val of_string_raw : string -> int ref -> t
(** Same as [of_string_exn] but takes as an extra argument the offset into the
string for reading. [off] will be mutated to an unspecified value during
the function call. Raises {!Parse_error} if it is an invalid or truncated
IP address. *)
val to_string : t -> string
(** [to_string ipv6] is the string representation of [ipv6], i.e.
[XXX:XX:X::XXX:XX]. *)
val to_buffer : Buffer.t -> t -> unit
(** [to_buffer buf ipv6] writes the string representation of [ipv6] into the
buffer [buf]. *)
val pp : Format.formatter -> t -> unit
[@@ocaml.toplevel_printer]
(** [pp f ipv6] outputs a human-readable representation of [ipv6] to the
formatter [f]. *)
(** {3 Octets conversion} *)
val of_octets : ?off:int -> string -> (t, [> `Msg of string ]) result
(** [of_octets ?off s] is the IPv6 address {!t} represented by the octets [s]
starting from offset [off] within the string. Returns a human-readable
error string if [s] is not at least [off+16] bytes long. [off] defaults to
0. *)
val of_octets_exn : ?off:int -> string -> t
(** [of_octets_exn ?off ipv6_octets] is the IPv6 address represented by
[ipv6_octets], starting from offset [off]. Raises {!Parse_error} if
[ipv6_octets] is not at least [off+16] bytes long. [off] defaults to 0. *)
val write_octets_exn : ?off:int -> t -> bytes -> unit
(** [write_octets_exn ?off ipv6 b] writes 16 bytes that encode [ipv6] into [b]
starting from offset [off] within [b]. [b] must be at least [off+16] bytes
long or a {!Parse_error} exception will be raised. *)
val write_octets :
?off:int -> t -> bytes -> (unit, [> `Msg of string ]) result
(** [write_octets ?off ipv6 b] writes 16 bytes that encode [ipv6] into [b]
starting from offset [off] within [b]. [b] must be at least [off+16] bytes
long or an error is returned. *)
val to_octets : t -> string
(** [to_octets ipv6] returns the 16 bytes representing the [ipv6] octets. *)
(** {3 Int conversion} *)
val of_int64 : int64 * int64 -> t
(** [of_int64 (ho, lo)] is the IPv6 address represented by two int64. *)
val to_int64 : t -> int64 * int64
(** [to_int64 ipv6] is the 128-bit packed encoding of [ipv6]. *)
val of_int32 : int32 * int32 * int32 * int32 -> t
(** [of_int32 (a, b, c, d)] is the IPv6 address represented by four int32. *)
val to_int32 : t -> int32 * int32 * int32 * int32
(** [to_int32 ipv6] is the 128-bit packed encoding of [ipv6]. *)
val of_int16 : int * int * int * int * int * int * int * int -> t
(** [of_int16 (a, b, c, d, e, f, g, h)] is the IPv6 address represented by
eight 16-bit int. *)
val to_int16 : t -> int * int * int * int * int * int * int * int
(** [to_int16 ipv6] is the 128-bit packed encoding of [ipv6]. *)
(** {3 MAC conversion} *)
val multicast_to_mac : t -> Macaddr.t
(** [multicast_to_mac ipv6] is the MAC address corresponding to the multicast
address [ipv6]. Described by
{{:https://tools.ietf.org/html/rfc2464#section-7} RFC 2464}. *)
(** {3 Host conversion} *)
val to_domain_name : t -> [ `host ] Domain_name.t
(** [to_domain_name ipv6] is the domain name label list for reverse lookups of
[ipv6]. This includes the [.ip6.arpa] suffix. *)
val of_domain_name : 'a Domain_name.t -> t option
(** [of_domain_name name] is [Some t] if the [name] has an [.ip6.arpa] suffix,
and an IPv6 address prefixed. *)
(** {3 Utility functions} *)
val succ : t -> (t, [> `Msg of string ]) result
(** [succ ipv6] is ip address next to [ipv6]. Returns a human-readable error
string if it's already the highest address. *)
val pred : t -> (t, [> `Msg of string ]) result
(** [pred ipv6] is ip address before [ipv6]. Returns a human-readable error
string if it's already the lowest address. *)
(** {3 Common addresses} *)
val unspecified : t
(** [unspecified] is ::. *)
val localhost : t
(** [localhost] is ::1. *)
val interface_nodes : t
(** [interface_nodes] is ff01::01. *)
val link_nodes : t
(** [link_nodes] is ff02::01. *)
val interface_routers : t
(** [interface_routers] is ff01::02. *)
val link_routers : t
(** [link_routers] is ff02::02. *)
val site_routers : t
(** [site_routers] is ff05::02. *)
(** A module for manipulating IPv6 network prefixes (CIDR). *)
module Prefix : sig
type addr = t
type t
(** Type of a internet protocol subnet: an address and a prefix length. *)
val mask : int -> addr
(** [mask n] is the pseudo-address of an [n] bit subnet mask. *)
val make : int -> addr -> t
(** [make n addr] is the cidr of [addr] with [n] bit prefix. *)
val prefix : t -> t
(** [prefix cidr] is the subnet prefix of [cidr] where all non-prefix bits
set to 0. *)
val network_address : t -> addr -> addr
(** [network_address cidr addr] is the address with prefix [cidr] and suffix
from [addr]. See <http://tools.ietf.org/html/rfc4291#section-2.3>. *)
val of_string_exn : string -> t
(** [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 : string -> (t, [> `Msg of string ]) result
(** Same as {!of_string_exn} but returns a result type instead of raising an
exception. *)
val of_string_raw : string -> int ref -> t
(** Same as {!of_string_exn} but takes as an extra argument the offset into
the string for reading. *)
val to_string : t -> string
(** [to_string cidr] is the CIDR notation string representation of [cidr],
i.e. XXX:XX:X::XXX/XX. *)
val pp : Format.formatter -> t -> unit
[@@ocaml.toplevel_printer]
(** [pp f cidr] outputs a human-readable representation of [cidr] to the
formatter [f]. *)
val to_buffer : Buffer.t -> t -> unit
(** [to_buffer buf cidr] writes the string representation of [cidr] to the
buffer [buf]. *)
val of_netmask_exn : netmask:addr -> address:addr -> t
(** [of_netmask_exn ~netmask ~address] is the subnet prefix of [address]
with netmask [netmask]. *)
val of_netmask :
netmask:addr -> address:addr -> (t, [> `Msg of string ]) result
(** [of_netmask ~netmask ~address] is the cidr of [address] with netmask
[netmask]. *)
val mem : addr -> t -> bool
(** [mem ip subnet] checks whether [ip] is found within [subnet]. *)
val subset : subnet:t -> network:t -> bool
(** [subset ~subnet ~network] checks whether [subnet] is contained within
[network]. *)
val of_addr : addr -> t
(** [of_addr ip] create a subnet composed of only one address, [ip]. It is
the same as [make 128 ip]. *)
val global_unicast_001 : t
(** Global Unicast 001, 2000::/3. *)
val unique_local : t
(** The Unique Local Unicast (ULA), fc00::/7. *)
val link : t
(** Link-Local Unicast, fe80::/64. *)
val multicast : t
(** The multicast network, ff00::/8. *)
val ipv4_mapped : t
(** IPv4-mapped addresses, ::ffff:0:0/96. *)
val noneui64_interface : t
(** Global Unicast addresses that don't use Modified EUI64 interface
identifiers, ::/3. *)
val solicited_node : t
(** Solicited-Node multicast addresses *)
val network : t -> addr
(** [network subnet] is the address for [subnet]. *)
val netmask : t -> addr
(** [netmask subnet] is the netmask for [subnet]. *)
val address : t -> addr
(** [address cidr] is the address for [cidr]. *)
val bits : t -> int
(** [bits subnet] is the bit size of the [subnet] prefix. *)
val first : t -> addr
(** [first subnet] is first valid unicast address in this [subnet]. *)
val last : t -> addr
(** [last subnet] is last valid unicast address in this [subnet]. *)
val hosts : ?usable:bool -> t -> addr Seq.t
(** [hosts subnet] is the sequence of host addresses in this [subnet]. By
default the Subnet-Router anycast address is omitted. This can be
changed by setting [usable] to false. *)
val subnets : int -> t -> t Seq.t
(** [subnets n subnet] is the sequence of subnets of [subnet] with a prefix
length of [n]. *)
include Map.OrderedType with type t := t
end
val scope : t -> scope
(** [scope ipv6] is the classification of [ipv6] by the {!scope} hierarchy. *)
val link_address_of_mac : Macaddr.t -> t
(** [link_address_of_mac mac] is the link-local address for an Ethernet
interface derived by the IEEE MAC -> EUI-64 map with the Universal/Local
bit complemented for IPv6.
@see <https://tools.ietf.org/html/rfc2464#section-4> RFC 2464 *)
val is_global : t -> bool
(** [is_global ipv6] is a predicate indicating whether [ipv6] globally
addresses a node. *)
val is_multicast : t -> bool
(** [is_multicast ipv6] is a predicate indicating whether [ipv6] is a
multicast address. *)
val is_private : t -> bool
(** [is_private ipv6] is a predicate indicating whether [ipv6] privately
addresses a node. *)
include Map.OrderedType with type t := t
module Set : Set.S with type elt := t
module Map : Map.S with type key := t
end
(** Type of either an IPv4 value or an IPv6 value *)
type ('v4, 'v6) v4v6 = V4 of 'v4 | V6 of 'v6
type t = (V4.t, V6.t) v4v6
(** Type of any IP address *)
val to_string : t -> string
(** [to_string addr] is the text string representation of [addr]. *)
val to_buffer : Buffer.t -> t -> unit
(** [to_buffer buf addr] writes the text string representation of [addr] into
[buf]. *)
val pp : Format.formatter -> t -> unit
[@@ocaml.toplevel_printer]
(** [pp f ip] outputs a human-readable representation of [ip] to the formatter
[f]. *)
val of_string_exn : string -> t
(** [of_string_exn s] parses [s] as an IPv4 or IPv6 address. Raises
{!Parse_error} if [s] is not a valid string representation of an IP address. *)
val of_string : string -> (t, [> `Msg of string ]) result
(** Same as {!of_string_exn} but returns a result type instead of raising an
exception. *)
val of_string_raw : string -> int ref -> t
(** Same as [of_string_exn] but takes as an extra argument the offset into the
string for reading. *)
val with_port_of_string :
default:int -> string -> (t * int, [> `Msg of string ]) result
(** [with_port_of_string ~default s] parses [s] as an IPv4 or IPv6 address with
a possible port seperated by a [':'] (if not, we use [default]). For IPv6,
due to the [':'] separator, only a full expansion of the IPv6 plus the port
lets us to interpret the last [:<int>] as the port. In other words:
- [::1:8080] returns the IPv6 [::1:8080] with the [default] port
- [0:0:0:0:0:0:0:1:8080] returns [::1] with the port [8080]. *)
val of_octets_exn : string -> t
(** [of_octets_exn octets] is the address {!t} represented by [octets]. The
[octets] must be 4 bytes long for a {!V4} or 16 if a {!V6}. Raises
{!Parse_error} if [octets] is not a valid representation of an address. *)
val of_octets : string -> (t, [> `Msg of string ]) result
(** Same as {!of_octets_exn} but returns a result type instead of raising an
exception. *)
val to_octets : t -> string
(** [to_octets addr] returns the bytes representing the [addr] octets, which
will be 4 bytes long if addr is a {!V4} or 16 if a {!V6}. *)
val v4_of_v6 : V6.t -> V4.t option
(** [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 to_v4 : t -> V4.t option
(** [to_v4 addr] is the IPv4 representation of [addr]. *)
val v6_of_v4 : V4.t -> V6.t
(** [v6_of_v4 ipv4] is the IPv6 representation of the IPv4 address [ipv4]. *)
val to_v6 : t -> V6.t
(** [to_v6 addr] is the IPv6 representation of [addr]. *)
val scope : t -> scope
(** [scope addr] is the classification of [addr] by the {!scope} hierarchy. *)
val is_global : t -> bool
(** [is_global addr] is a predicate indicating whether [addr] globally addresses
a node. *)
val is_multicast : t -> bool
(** [is_multicast addr] is a predicate indicating whether [addr] is a multicast
address. *)
val is_private : t -> bool
(** [is_private addr] is a predicate indicating whether [addr] privately
addresses a node. *)
val multicast_to_mac : t -> Macaddr.t
(** [multicast_to_mac addr] is the MAC address corresponding to the multicast
address [addr]. See {!V4.multicast_to_mac} and {!V6.multicast_to_mac}.*)
val to_domain_name : t -> [ `host ] Domain_name.t
(** [to_domain_name addr] is the domain name label list for reverse lookups of
[addr]. This includes the [.in-addr.arpa] or [.ip6.arpa] suffix. *)
val of_domain_name : 'a Domain_name.t -> t option
(** [of_domain_name name] is [Some t] if the [name] has an [.in-addr.arpa] or
[ip6.arpa] suffix, and an IP address prefixed. *)
val succ : t -> (t, [> `Msg of string ]) result
(** [succ addr] is ip address next to [addr]. Returns a human-readable error
string if it's already the highest address. *)
val pred : t -> (t, [> `Msg of string ]) result
(** [pred addr] is ip address before [addr]. Returns a human-readable error
string if it's already the lowest address. *)
module Prefix : sig
type addr = t
type t = (V4.Prefix.t, V6.Prefix.t) v4v6
(** Type of a internet protocol subnet *)
val to_string : t -> string
(** [to_string subnet] is the text string representation of [subnet]. *)
val to_buffer : Buffer.t -> t -> unit
(** [to_buffer buf subnet] writes the text string representation of [subnet]
into [buf]. *)
val pp : Format.formatter -> t -> unit
[@@ocaml.toplevel_printer]
(** [pp f subnet] outputs a human-readable representation of [subnet] to the
formatter [f]. *)
val of_string_exn : string -> t
(** [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 : string -> (t, [> `Msg of string ]) result
(** Same as {!of_string_exn} but returns a result type instead of raising an
exception. *)
val of_string_raw : string -> int ref -> t
(** Same as {!of_string_exn} but takes as an extra argument the offset into
the string for reading. *)
val v4_of_v6 : V6.Prefix.t -> V4.Prefix.t option
(** [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 to_v4 : t -> V4.Prefix.t option
(** [to_v4 subnet] is the IPv4 representation of [subnet]. *)
val v6_of_v4 : V4.Prefix.t -> V6.Prefix.t
(** [v6_of_v4 ipv4] is the IPv6 representation of the IPv4 subnet [ipv4]. *)
val to_v6 : t -> V6.Prefix.t
(** [to_v6 subnet] is the IPv6 representation of [subnet]. *)
val mem : addr -> t -> bool
(** [mem ip subnet] checks whether [ip] is found within [subnet]. *)
val subset : subnet:t -> network:t -> bool
(** [subset ~subnet ~network] checks whether [subnet] is contained within
[network]. *)
val of_addr : addr -> t
(** [of_addr ip] create a subnet composed of only one address, [ip].*)
val network : t -> addr
(** [network subnet] is the address for [subnet]. *)
val netmask : t -> addr
(** [netmask subnet] is the netmask for [subnet]. *)
val address : t -> addr
(** [address cidr] is the address for [cidr]. *)
val bits : t -> int
(** [bits cidr] is the bit size of the [cidr] prefix. *)
val first : t -> addr
(** [first subnet] is first valid unicast address in this [subnet]. *)
val last : t -> addr
(** [last subnet] is last valid unicast address in this [subnet]. *)
val hosts : ?usable:bool -> t -> (V4.t Seq.t, V6.t Seq.t) v4v6
(** [hosts cidr] is the sequence of host addresses in this [cidr]. By default,
the network and broadcast addresses are omitted for IPv4. In the case of
IPv6, the Subnet-Router anycast address is omitted by default. This can be
changed by setting [usable] to false. *)
val subnets : int -> t -> (V4.Prefix.t Seq.t, V6.Prefix.t Seq.t) v4v6
(** [subnets n cidr] is the sequence of subnets of [cidr] with a prefix length
of [n]. *)
include Map.OrderedType with type t := t
end
include Map.OrderedType with type t := t
module Set : Set.S with type elt := t
module Map : Map.S with type key := t

View file

@ -0,0 +1,63 @@
(*
* Copyright (c) 2019 Anil Madhavapeddy
* Copyright (c) 2014 Nicolás Ojeda Bär
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*)
let need_more x = Ipaddr.Parse_error ("not enough data", x)
let try_with_result fn a =
try Ok (fn a)
with Ipaddr.Parse_error (msg, _) -> Error (`Msg ("Ipaddr: " ^ msg))
module V4 = struct
let of_cstruct_exn cs =
let len = Cstruct.length cs in
if len < 4 then raise (need_more (Cstruct.to_string cs));
Ipaddr.V4.of_int32 (Cstruct.BE.get_uint32 cs 0)
let of_cstruct cs = try_with_result of_cstruct_exn cs
let write_cstruct_exn i cs =
let len = Cstruct.length cs in
if len < 4 then raise (need_more (Cstruct.to_string cs));
Cstruct.BE.set_uint32 cs 0 (Ipaddr.V4.to_int32 i)
let to_cstruct ?(allocator = Cstruct.create) i =
let cs = allocator 4 in
write_cstruct_exn i cs;
cs
end
module V6 = struct
open Ipaddr.V6
let of_cstruct_exn cs =
let len = Cstruct.length cs in
if len < 16 then raise (need_more (Cstruct.to_string cs));
of_octets_exn (Cstruct.to_string ~len:16 cs)
let of_cstruct cs = try_with_result of_cstruct_exn cs
let write_cstruct_exn i cs =
let len = Cstruct.length cs in
if len < 16 then raise (need_more (Cstruct.to_string cs));
Cstruct.blit_from_string (to_octets i) 0 cs 0 16
let to_cstruct ?(allocator = Cstruct.create) i =
let cs = allocator 16 in
write_cstruct_exn i cs;
cs
end

View file

@ -0,0 +1,59 @@
(*
* Copyright (c) 2019 Anil Madhavapeddy
* Copyright (c) 2014 Nicolás Ojeda Bär
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*)
(** Convert to and from Cstructs and IP addresses *)
(** Ipv4 address conversions *)
module V4 : sig
val of_cstruct : Cstruct.t -> (Ipaddr.V4.t, [> `Msg of string ]) result
(** [of_cstruct c] parses the first 4 octets of [c] into an IPv4 address. *)
val of_cstruct_exn : Cstruct.t -> Ipaddr.V4.t
(** [of_cstruct_exn] parses the first 4 octets of [c] into an IPv4 address.
Raises {!Ipaddr.Parse_failure} on error. *)
val to_cstruct : ?allocator:(int -> Cstruct.t) -> Ipaddr.V4.t -> Cstruct.t
(** [to_cstruct ipv4] is a cstruct of length 4 encoding [ipv4]. The cstruct is
allocated using [allocator]. If [allocator] is not provided,
[Cstruct.create] is used. *)
val write_cstruct_exn : Ipaddr.V4.t -> Cstruct.t -> unit
(** [write_cstruct_exn ipv4 cs] writes 4 bytes into [cs] representing the
[ipv4] address octets. Raises {!Ipaddr.Parse_error} if [cs] is not at
least 4 bytes long. *)
end
(** Ipv6 address conversions *)
module V6 : sig
val of_cstruct : Cstruct.t -> (Ipaddr.V6.t, [> `Msg of string ]) result
(** [of_cstruct c] parses the first 16 octets of [c] into an IPv6 address. *)
val of_cstruct_exn : Cstruct.t -> Ipaddr.V6.t
(** [of_cstruct_exn] parses the first 16 octets of [c] into an IPv6 address.
Raises {!Ipaddr.Parse_failure} on error. *)
val to_cstruct : ?allocator:(int -> Cstruct.t) -> Ipaddr.V6.t -> Cstruct.t
(** [to_cstruct ipv6] is a cstruct of length 16 encoding [ipv6]. The cstruct
is allocated using [allocator]. If [allocator] is not provided,
[Cstruct.create] is used. *)
val write_cstruct_exn : Ipaddr.V6.t -> Cstruct.t -> unit
(** [write_cstruct_exn ipv6 cs] writes 16 bytes into [cs] representing the
[ipv6] address octets. Raises {!Ipaddr.Parse_error} if [cs] is not at
least 16 bytes long. *)
end

View file

@ -0,0 +1,91 @@
(*
* Copyright (c) 2018 Anil Madhavapeddy <anil@recoil.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*)
open Sexplib0
let of_sexp fn = function
| Sexp.List _ -> failwith "expecting sexp atom"
| Sexp.Atom s -> (
match fn s with Ok r -> r | Error (`Msg msg) -> failwith msg)
let to_sexp fn t = Sexp.Atom (fn t)
module V4 = struct
module I = Ipaddr.V4
type t = I.t
let sexp_of_t = to_sexp I.to_string
let t_of_sexp = of_sexp I.of_string
let compare = I.compare
module Prefix = struct
module I = Ipaddr.V4.Prefix
type addr = I.addr
type t = I.t
let sexp_of_t = to_sexp I.to_string
let t_of_sexp = of_sexp I.of_string
let compare = I.compare
end
end
module V6 = struct
module I = Ipaddr.V6
type t = I.t
let sexp_of_t = to_sexp I.to_string
let t_of_sexp = of_sexp I.of_string
let compare = I.compare
module Prefix = struct
module I = Ipaddr.V6.Prefix
type addr = I.addr
type t = I.t
let sexp_of_t = to_sexp I.to_string
let t_of_sexp = of_sexp I.of_string
let compare = I.compare
end
end
module I = Ipaddr
type t = I.t
let sexp_of_t = to_sexp I.to_string
let t_of_sexp = of_sexp I.of_string
let compare = I.compare
type scope = I.scope
let sexp_of_scope = to_sexp I.string_of_scope
let scope_of_sexp = of_sexp I.scope_of_string
module Prefix = struct
module I = Ipaddr.Prefix
type addr = I.addr
type t = I.t
let sexp_of_t = to_sexp I.to_string
let t_of_sexp = of_sexp I.of_string
let compare = I.compare
end

View file

@ -0,0 +1,92 @@
(*
* Copyright (c) 2018 Anil Madhavapeddy <anil@recoil.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*)
(** serialisers to and from {!Ipaddr} and s-expression {!Sexplib0} format
To use these with ppx-based derivers, simply replace the reference to the
{!Ipaddr} type definition with {!Ipaddr_sexp} instead. That will import the
sexp-conversion functions, and the actual type definitions are simply
aliases to the corresponding type within {!Ipaddr}. For example, you might
do:
{[
type t = { ip : Ipaddr_sexp.t; mac : Macaddr_sexp.t } [@@deriving sexp]
]}
The actual types of the records will be aliases to the main library types,
and there will be two new functions available as converters.
{[
type t = { ip : Ipaddr.t; mac : Macaddr.t }
val sexp_of_t : t -> Sexplib0.t
val t_of_sexp : Sexplib0.t -> t
]} *)
type t = Ipaddr.t
val sexp_of_t : Ipaddr.t -> Sexplib0.Sexp.t
val t_of_sexp : Sexplib0.Sexp.t -> Ipaddr.t
val compare : Ipaddr.t -> Ipaddr.t -> int
type scope = Ipaddr.scope
val sexp_of_scope : Ipaddr.scope -> Sexplib0.Sexp.t
val scope_of_sexp : Sexplib0.Sexp.t -> Ipaddr.scope
module V4 : sig
type t = Ipaddr.V4.t
val sexp_of_t : Ipaddr.V4.t -> Sexplib0.Sexp.t
val t_of_sexp : Sexplib0.Sexp.t -> Ipaddr.V4.t
val compare : Ipaddr.V4.t -> Ipaddr.V4.t -> int
module Prefix : sig
type addr = Ipaddr.V4.Prefix.addr
type t = Ipaddr.V4.Prefix.t
val sexp_of_t : Ipaddr.V4.Prefix.t -> Sexplib0.Sexp.t
val t_of_sexp : Sexplib0.Sexp.t -> Ipaddr.V4.Prefix.t
val compare : Ipaddr.V4.Prefix.t -> Ipaddr.V4.Prefix.t -> int
end
end
module V6 : sig
type t = Ipaddr.V6.t
val sexp_of_t : Ipaddr.V6.t -> Sexplib0.Sexp.t
val t_of_sexp : Sexplib0.Sexp.t -> Ipaddr.V6.t
val compare : Ipaddr.V6.t -> Ipaddr.V6.t -> int
module Prefix : sig
type addr = Ipaddr.V6.Prefix.addr
type t = Ipaddr.V6.Prefix.t
val sexp_of_t : Ipaddr.V6.Prefix.t -> Sexplib0.Sexp.t
val t_of_sexp : Sexplib0.Sexp.t -> Ipaddr.V6.Prefix.t
val compare : Ipaddr.V6.Prefix.t -> Ipaddr.V6.Prefix.t -> int
end
end
module Prefix : sig
type addr = Ipaddr.Prefix.addr
type t = Ipaddr.Prefix.t
val sexp_of_t : Ipaddr.Prefix.t -> Sexplib0.Sexp.t
val t_of_sexp : Sexplib0.Sexp.t -> Ipaddr.Prefix.t
val compare : Ipaddr.Prefix.t -> Ipaddr.Prefix.t -> int
end

View file

@ -0,0 +1,26 @@
let printers =
[
"Ipaddr.pp";
"Ipaddr.Prefix.pp";
"Ipaddr.V4.pp";
"Ipaddr.V4.Prefix.pp";
"Ipaddr.V6.pp";
"Ipaddr.V6.Prefix.pp";
"Macaddr.pp";
]
let eval_string ?(print_outcome = false) ?(err_formatter = Format.err_formatter)
str =
let lexbuf = Lexing.from_string str in
let phrase = !Toploop.parse_toplevel_phrase lexbuf in
Toploop.execute_phrase print_outcome err_formatter phrase
let rec install_printers = function
| [] -> true
| printer :: printers ->
let cmd = Printf.sprintf "#install_printer %s;;" printer in
eval_string cmd && install_printers printers
let () =
if not (install_printers printers) then
Format.eprintf "Problem installing Ipaddr-printers@."

View file

@ -0,0 +1,6 @@
val printers : string list
val eval_string :
?print_outcome:bool -> ?err_formatter:Format.formatter -> string -> bool
val install_printers : string list -> bool

View file

@ -0,0 +1,31 @@
(*
* Copyright (c) 2014 Anil Madhavapeddy <anil@recoil.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*)
let to_inet_addr t = Unix.inet_addr_of_string (Ipaddr.to_string t)
let of_inet_addr t = Ipaddr.of_string_exn (Unix.string_of_inet_addr t)
module V4 = struct
let to_inet_addr t = Unix.inet_addr_of_string (Ipaddr.V4.to_string t)
let of_inet_addr_exn t = Ipaddr.V4.of_string_exn (Unix.string_of_inet_addr t)
let of_inet_addr t = try Some (of_inet_addr_exn t) with _ -> None
end
module V6 = struct
let to_inet_addr t = Unix.inet_addr_of_string (Ipaddr.V6.to_string t)
let of_inet_addr_exn t = Ipaddr.V6.of_string_exn (Unix.string_of_inet_addr t)
let of_inet_addr t = try Some (of_inet_addr_exn t) with _ -> None
end

View file

@ -0,0 +1,58 @@
(*
* Copyright (c) 2014 Anil Madhavapeddy <anil@recoil.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*)
(** Convert to and from [Unix] to [Ipaddr] representations
{e v5.6.1 - {{:https://github.com/mirage/ocaml-ipaddr} homepage}} *)
val to_inet_addr : Ipaddr.t -> Unix.inet_addr
(** [to_inet_addr ip] is the {!Unix.inet_addr} equivalent of the IPv4 or IPv6
address [ip]. *)
val of_inet_addr : Unix.inet_addr -> Ipaddr.t
(** [of_inet_addr ip] is the {!Ipaddr.t} equivalent of the {!Unix.inet_addr}
[ip]. *)
module V4 : sig
val to_inet_addr : Ipaddr.V4.t -> Unix.inet_addr
(** [to_inet_addr ip] is the {!Unix.inet_addr} equivalent of the IPv4 address
[ip]. *)
val of_inet_addr_exn : Unix.inet_addr -> Ipaddr.V4.t
(** [of_inet_addr_exn ip] is the {!Ipaddr.t} equivalent of the
{!Unix.inet_addr} [ip] IPv4 address. Raises {!Ipaddr.Parse_error} if [ip]
is not a valid representation of an IPv4 address. *)
val of_inet_addr : Unix.inet_addr -> Ipaddr.V4.t option
(** Same as [of_inet_addr_exn] but returns an option type instead of raising
an exception. *)
end
module V6 : sig
val to_inet_addr : Ipaddr.V6.t -> Unix.inet_addr
(** [to_inet_addr ip] is the {!Unix.inet_addr} equivalent of the IPv6 address
[ip]. *)
val of_inet_addr_exn : Unix.inet_addr -> Ipaddr.V6.t
(** [of_inet_addr_exn ip] is the {!Ipaddr.t} equivalent of the
{!Unix.inet_addr} [ip] IPv6 address. Raises {!Ipaddr.Parse_error} if [ip]
is not a valid representation of an IPv6 address. *)
val of_inet_addr : Unix.inet_addr -> Ipaddr.V6.t option
(** Same as [of_inet_addr_exn] but returns an option type instead of raising
an exception. *)
end

View file

@ -0,0 +1,114 @@
(*
* Copyright (c) 2010 Anil Madhavapeddy <anil@recoil.org>
* Copyright (c) 2014 David Sheets <sheets@alum.mit.edu>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*)
exception Parse_error of string * string
let need_more x = Parse_error ("not enough data", x)
let try_with_result fn a =
try Ok (fn a) with Parse_error (msg, _) -> Error (`Msg ("Macaddr: " ^ msg))
type t = Bytes.t (* length 6 only *)
let compare = Bytes.compare
(* Raw MAC address off the wire (network endian) *)
let of_octets_exn x =
if String.length x <> 6 then raise (Parse_error ("MAC is exactly 6 bytes", x))
else Bytes.of_string x
let of_octets x = try_with_result of_octets_exn x
let int_of_hex_char c =
let c = int_of_char (Char.uppercase_ascii c) - 48 in
if c > 9 then
if c > 16 then c - 7 (* upper hex offset *) else -1 (* :;<=>?@ *)
else c
let is_hex i = i >= 0 && i < 16
let bad_char i s =
let msg = Printf.sprintf "invalid character '%c' at %d" s.[i] i in
Parse_error (msg, s)
let parse_hex_int term s i =
let len = String.length s in
let rec hex prev =
let j = !i in
if j >= len then prev
else
let c = s.[j] in
let k = int_of_hex_char c in
if is_hex k then (
incr i;
hex ((prev lsl 4) + k))
else if List.mem c term then prev
else raise (bad_char j s)
in
let i = !i in
if i < len then
if is_hex (int_of_hex_char s.[i]) then hex 0 else raise (bad_char i s)
else raise (need_more s)
let parse_sextuple s i =
let m = Bytes.create 6 in
try
let p = !i in
Bytes.set m 0 (Char.chr (parse_hex_int [ ':'; '-' ] s i));
if !i >= String.length s then raise (need_more s)
else
let sep = [ s.[!i] ] in
if !i - p <> 2 then raise (Parse_error ("hex pairs required", s));
incr i;
for k = 1 to 4 do
let p = !i in
Bytes.set m k (Char.chr (parse_hex_int sep s i));
if !i - p <> 2 then raise (Parse_error ("hex pairs required", s));
incr i
done;
let p = !i in
Bytes.set m 5 (Char.chr (parse_hex_int [] s i));
if !i - p <> 2 then raise (Parse_error ("hex pairs required", s));
m
with Invalid_argument _ ->
raise (Parse_error ("address segment too large", s))
(* Read a MAC address colon-separated string *)
let of_string_exn x = parse_sextuple x (ref 0)
let of_string x = try_with_result of_string_exn x
let chri x i = Char.code (Bytes.get x i)
let to_string ?(sep = ':') x =
Printf.sprintf "%02x%c%02x%c%02x%c%02x%c%02x%c%02x" (chri x 0) sep (chri x 1)
sep (chri x 2) sep (chri x 3) sep (chri x 4) sep (chri x 5)
let to_octets x = Bytes.to_string x
let pp ppf i = Format.fprintf ppf "%s" (to_string i)
let broadcast = Bytes.make 6 '\255'
let make_local bytegenf =
let x = Bytes.create 6 in
(* set locally administered and unicast bits *)
Bytes.set x 0 (Char.chr (((bytegenf 0 lor 2) lsr 1) lsl 1));
for i = 1 to 5 do
Bytes.set x i (Char.chr (bytegenf i))
done;
x
let get_oui x = (chri x 0 lsl 16) lor (chri x 1 lsl 8) lor chri x 2
let is_local x = (chri x 0 lsr 1) land 1 = 1
let is_unicast x = chri x 0 land 1 = 0

View file

@ -0,0 +1,78 @@
(*
* Copyright (c) 2010-2011 Anil Madhavapeddy <anil@recoil.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*)
(** A library for manipulation of MAC address representations.
{e v5.6.1 - {{:https://github.com/mirage/ocaml-ipaddr} homepage}} *)
exception Parse_error of string * string
(** [Parse_error (err,packet)] is raised when parsing of the MAC address syntax
fails. [err] contains a human-readable error and [packet] is the original
octet list that failed to parse. *)
type t
(** Type of the hardware address (MAC) of an ethernet interface. *)
(** {2 Functions converting MAC addresses to/from octets/string} *)
val of_octets_exn : string -> t
(** [of_octets_exn buf] is the hardware address extracted from [buf]. Raises
[Parse_error] if [buf] has not length 6. *)
val of_octets : string -> (t, [> `Msg of string ]) result
(** Same as {!of_octets_exn} but returns a result type instead of raising an
exception. *)
val of_string_exn : string -> t
(** [of_string_exn mac_string] is the human-readable hardware address
represented by [mac_string]. Raises {!Parse_error} if [mac_string] is not a
valid representation of a MAC address. *)
val of_string : string -> (t, [> `Msg of string ]) result
(** Same as {!of_string_exn} but returns a result type instead of raising an
exception. *)
val to_octets : t -> string
(** [to_octets mac_addr] is a string of size 6 encoding [mac_addr] as a sequence
of bytes. *)
val to_string : ?sep:char -> t -> string
(** [to_string ?(sep=':') mac_addr] is the [sep]-separated string representation
of [mac_addr], i.e. [xx:xx:xx:xx:xx:xx]. *)
val pp : Format.formatter -> t -> unit
[@@ocaml.toplevel_printer]
(** [pp f mac_addr] outputs a human-readable representation of [mac_addr] to the
formatter [f]. *)
val broadcast : t
(** [broadcast] is [ff:ff:ff:ff:ff:ff]. *)
val make_local : (int -> int) -> t
(** [make_local bytegen] creates a unicast, locally administered MAC address
given a function mapping octet offset to octet value. *)
val get_oui : t -> int
(** [get_oui macaddr] is the integer organization identifier for [macaddr]. *)
val is_local : t -> bool
(** [is_local macaddr] is the predicate on the locally administered bit of
[macaddr]. *)
val is_unicast : t -> bool
(** [is_unicast macaddr] the is the predicate on the unicast bit of [macaddr]. *)
include Map.OrderedType with type t := t

View file

@ -0,0 +1,39 @@
(*
* Copyright (c) 2019 Anil Madhavapeddy
* Copyright (c) 2014 Nicolás Ojeda Bär
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*)
let try_with_result fn a =
try Ok (fn a)
with Macaddr.Parse_error (msg, _) -> Error (`Msg ("Macaddr: " ^ msg))
let of_cstruct_exn cs =
if Cstruct.length cs <> 6 then
raise (Macaddr.Parse_error ("MAC is exactly 6 bytes", Cstruct.to_string cs))
else Cstruct.to_string cs |> Macaddr.of_octets_exn
let of_cstruct cs = try_with_result of_cstruct_exn cs
let write_cstruct_exn (mac : Macaddr.t) cs =
let len = Cstruct.length cs in
let mac = Macaddr.to_octets mac in
if len <> 6 then raise (Macaddr.Parse_error ("MAC is exactly 6 bytes", mac));
Cstruct.blit_from_string mac 0 cs 0 6
let to_cstruct ?(allocator = Cstruct.create) mac =
let cs = allocator 6 in
write_cstruct_exn mac cs;
cs

View file

@ -0,0 +1,35 @@
(*
* Copyright (c) 2019 Anil Madhavapeddy
* Copyright (c) 2014 Nicolás Ojeda Bär
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*)
(** Convert to and from Cstructs and MAC address. *)
val of_cstruct : Cstruct.t -> (Macaddr.t, [> `Msg of string ]) result
(** [of_cstruct c] parses the 6 octets of [c] into a MAC address. *)
val of_cstruct_exn : Cstruct.t -> Macaddr.t
(** [of_cstruct_exn] parses the 6 octets of [c] into a MAC address. Raises
{!Macaddr.Parse_failure} on error. *)
val to_cstruct : ?allocator:(int -> Cstruct.t) -> Macaddr.t -> Cstruct.t
(** [to_cstruct mac] is a cstruct of length 4 encoding [ipv4]. The cstruct is
allocated using [allocator]. If [allocator] is not provided,
[Cstruct.create] is used. *)
val write_cstruct_exn : Macaddr.t -> Cstruct.t -> unit
(** [write_cstruct_exn mac cs] writes 6 bytes into [cs] representing the [mac]
address octets. Raises {!Macaddr.Parse_error} if [cs] is not 6 bytes long. *)

View file

@ -0,0 +1,31 @@
(*
* Copyright (c) 2018 Anil Madhavapeddy <anil@recoil.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*)
open Sexplib0
let of_sexp fn = function
| Sexp.List _ -> failwith "expecting sexp atom"
| Sexp.Atom s -> (
match fn s with Ok r -> r | Error (`Msg msg) -> failwith msg)
let to_sexp fn t = Sexp.Atom (fn t)
type t = Macaddr.t
let sexp_of_t = to_sexp Macaddr.to_string
let t_of_sexp = of_sexp Macaddr.of_string
let compare = Macaddr.compare

View file

@ -0,0 +1,44 @@
(*
* Copyright (c) 2018 Anil Madhavapeddy <anil@recoil.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*)
(** serialisers to and from {!Macaddr} and s-expression {!Sexplib0} format
To use these with ppx-based derivers, simply replace the reference to the
{!Macaddr} type definition with {!Macaddr_sexp} instead. That will import
the sexp-conversion functions, and the actual type definitions are simply
aliases to the corresponding type within {!Ipaddr}. For example, you might
do:
{[
type t = { ip : Ipaddr_sexp.t; mac : Macaddr_sexp.t } [@@deriving sexp]
]}
The actual types of the records will be aliases to the main library types,
and there will be two new functions available as converters.
{[
type t = { ip : Ipaddr.t; mac : Macaddr.t }
val sexp_of_t : t -> Sexplib0.t
val t_of_sexp : Sexplib0.t -> t
]} *)
type t = Macaddr.t
val sexp_of_t : Macaddr.t -> Sexplib0.Sexp.t
val t_of_sexp : Sexplib0.Sexp.t -> Macaddr.t
val compare : Macaddr.t -> Macaddr.t -> int

View file

@ -0,0 +1,17 @@
let printers = [ "Macaddr.pp" ]
let eval_string ?(print_outcome = false) ?(err_formatter = Format.err_formatter)
str =
let lexbuf = Lexing.from_string str in
let phrase = !Toploop.parse_toplevel_phrase lexbuf in
Toploop.execute_phrase print_outcome err_formatter phrase
let rec install_printers = function
| [] -> true
| printer :: printers ->
let cmd = Printf.sprintf "#install_printer %s;;" printer in
eval_string cmd && install_printers printers
let () =
if not (install_printers printers) then
Format.eprintf "Problem installing Macaddr-printers@."