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,4 @@
_build
*.install
**/*.merlin
.*.swp

View file

@ -0,0 +1,5 @@
version = 0.26.2
profile = conventional
break-infix = fit-or-vertical
parse-docstrings = true
indicate-multiline-delimiters = no

View file

@ -0,0 +1,330 @@
## v5.6.1 (2025-08-01)
* Add Ipaddr.Prefix.bits (#125 @psafont)
## v5.6.0 (2024-05-22)
* Add host and subnet Seq.t iterators for Ipaddr.V4.prefix, Ipaddr.V6.Prefix
and Ipaddr.Prefix (#107 @verbosemode @dinosaure)
* Ipaddr.V4.compare: use Int32.unsigned_compare, as provided since OCaml 4.08
(#118 @reynir)
* Ipaddr.V6.t is a string, not a byte vector anymore (so it is immutable)
(#119 @reynir, restoring 4.08 compatibility #121)
* Provide Ipaddr.Prefix.address (since 5.0.0, Ipaddr.V4.Prefix.address and
Ipaddr.V6.Prefix.address have been provided, but Ipaddr.Prefix.address was
forgotten) (#122 @hannesm)
* Fix further docstrings (#123, fixes #81, @hannesm @reynir)
## v5.5.0 (2023-03-31)
* add `Ipaddr` `of_octet` functions (#117, @ryangibb).
## v5.4.0 (2023-03-13)
* Use Bytes.t for IPv6 addresses (#115 @verbosemode, fixes #16 @dsheets)
* Also fixes `V6.to_int64` (reported by @RyanGibb in #113)
## v5.3.1 (2022-07-04)
* Remove stdlib-shims dependency, require OCaml 4.08+ (@hannesm, #112)
* Switch to ounit2 (@Alessandro-Barbieri, #111)
## v5.3.0 (2022-03-04)
* Add `with_port_of_string` function (@dinosaure, @hannesm, #108)
* **breaking-change** Be restrictive on `Ipaddr.of_string` (@dinosaure, @hannesm, #109)
Before this release, `Ipaddr.of_string` accepts remaining bytes and returns
a valid value such as `"127.0.0.1aaaa"` is valid. Now, `ipaddr` does not
accept a string with remaining bytes.
## v5.2.0 (2021-09-11)
* Use Cstruct.length instead of deprecated Cstruct.len (#106, @hannesm)
* Provide instantiated functors Set, Map, V4.Set, V4.Map, V6.Set, V6.Map
(#106, @hannesm)
## v5.1.0 (2021-06-08)
* Reject octal notation in IPv4 (cve-2021-29921, #104, @jsachs)
* CI fixes, upgrade to ocamlformat 0.18 (@hannesm)
## v5.0.1 (2020-09-30)
* Fix V4.Prefix.broadcast and last with /32 prefixes (#102 @verbosemode)
## v5.0.0 (2020-06-16)
* Do not zero out the non-prefix-length part of the address in
`{V4,V6}.Prefix.t` (#99 @hannesm)
Removed `{V4,V6}.Prefix.of_address_string{,_exn}` and
`{V4,V6}.Prefix.to_address_{string.buffer}`
To port code:
- if you rely on `Prefix.of_string` to zero out the non-prefix-length address
bits, call `Prefix.prefix : t -> t` subsequently.
- `Prefix.of_address_string{,_exn}` can be replaced by
`Prefix.of_string{,_exn}`, to retrieve the address use
`Prefix.address : t -> addr`.
- The `Prefix.to_address_{string,buffer}` can be replaced by
`Prefix.to_{string,buffer}`, where `Prefix.t` already contains the IP
address to be printed.
- Instead of passing `{V4,V6}.t * {V4,V6}.Prefix.t` for an
address and subnet configuration, `{V4,V6}.Prefix.t` is sufficient.
* Implement `{V4,V6,}.succ`, `{V4,V6,}.pred`, `{V4,V6}.Prefix.first`, and
`{V4,V6}.Prefix.last` functions (#94 @NightBlues)
* Rename `Prefix.of_netmask` to `Prefix.of_netmask_exn` with labelled
arguments (~netmask and ~address), provide `Prefix.of_netmask` which returns
a (t, [> `Msg of string ]) result value (#95 @hannesm)
* Fix undefined behaviour of `V4.Prefix.mem` with a CIDR with prefix length 0
(#98 @verbosemode)
* Use stdlib-shims to prevent deprecation warnings on OCaml 4.08
(@avsm)
* Remove unnecessary "sexplib0" dependency (#95 @hannesm)
* Remove "{build}" directive from "dune" dependency (#93 @CraigFe)
## v4.0.0 (2019-07-12)
* Rename the `to/from_bytes` functions to refer to `octets`
instead. This distinguishes the meaning of human-readable
addresses (`string`s in this library) and byte-packed
representations(`octet`s in this library) from the OCaml
`bytes` type that represents mutable strings.
Porting code should just be a matter of renaming functions
such as:
- `Ipaddr.of_bytes` becomes `Ipaddr.of_octets`
- `Macaddr.to_bytes` becomes `Macaddr.to_octets`
* Introduce new `write_octets` functions that can write
octet representations of IPv4/v6 into an existing bytestring.
* Use the `domain-name` library to produce domain names
from IP addresses.
* Remove the `ipaddr.sexp` and `macaddr.sexp` ocamlfind
subpackages and instead have `ipaddr-sexp` and `macaddr-sexp`
to match the opam package names.
* Add new `Ipaddr_cstruct` and `Macaddr_cstruct` libraries
for conversion to/from cstructs (#36 @nojb @avsm)
## v3.1.0 (2019-03-02)
* Do not leak a `Not_found` exception when parsing `[:`
in IPv6 and instead raise `Parse_error` as other errors
do (found by fuzz testing in #84 by @dinosaure)
* Install automatic toplevel printers for the Ipaddr
types via `[@@ocaml.toplevel_printer]`. This enables
utop to automatically install the printers (@avsm)
## 3.0.0 (2019-01-02)
This release features several backwards incompatible changes,
but ones that should increase the portability and robustness
of the library.
* Remove the sexp serialisers from the main interface in favour
of `pp` functions. Use the `Ipaddr_sexp` module if you still
need a sexp serialiser.
To use these with ppx-based derivers, simply replace the
reference to the `Ipaddr` type definition with `Ipaddr_sexp`.
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. The signature after ppx has run will be:
```
type t = {
ip: Ipaddr.t;
mac: Macaddr.t;
}
val sexp_of_t : t -> Sexplib0.t
val t_of_sexp : Sexplib0.t -> t
```
* Break out the `Macaddr` module into a separate opam package so
that the `Ipaddr` module can be wrapped. Use the `macaddr`
opam library now if you need just the MAC address functionality.
* Replace all the `of_string/bytes` functions that formerly returned
option types with the `Rresult` result types instead. This stops
the cause of the exception from being swallowed, and the error
message in the new functions can be displayed usefully.
* In the `Ipaddr.V6.to_string` and `to_buffer` functions, remove the
optional labelled argument `v4` and always output v4-mapped strings
as recommended by RFC5952. (#80 by @hannesm).
* Remove `pp_hum` which was deprecated in 2.9.0.
* Sexplib0 is now used which is more lightweight tha the full
Sexplib library. Minimum OCaml version is now 4.04.0+ as a result
of this dependency.
* Improvements to the ocamldoc formatting strings for better
layout and odoc compatibility.
## 2.9.0 (2018-12-11)
* Add `pp` functions for prettyprinting and deprecate `pp_hum` variants.
The two functions are currently the same, so porting is just a matter
of replacing existing uses of `pp_hum` with `pp` (#71 @verbosemode)
* Fix deprecation warnings on newer OCaml standard libraries (#74 @cfcs).
* Fix `base-unix` depopt to be a real dependency (#68 @rgrinberg).
* Fix missing `sexplib` dependency (#66 #67 @bmillwood).
* Port to Dune from jbuilder and update opam metadata to 2.0 format (#76 @avsm).
* Remove unused variable and bindings warnings in the implementation and
signatures (#76 @avsm)
* Fix toplevel handling of the `ipaddr.top` package by linking
to compiler-libs instead of compiler-libs.toplevel (#76 @avsm based on
fix in mirage/ocaml-uri#130 by @yallop)
* Update Travis to test latest distros by using their aliases (#76 @avsm)
* Upgrade opam metadata to the 2.0 format (#76 @avsm)
## 2.8.0 (2017-06-01)
* Port to Jbuilder (#65 @vbmithr @avsm).
There should be no observable changes, except that `Ipaddr_unix` is now
in a separate subdirectory. This means that packages that implicitly
depended on the module without including the ocamlfind `ipaddr.unix`
package may now fail. Just adding the ocamlfind dependency will fix it,
and is backwards compatible with older Ipaddr releases.
* Minimum version of OCaml required is now 4.03.0 (formerly was 4.02.2),
due to the use of recent `ppx_sexp_conv` with Jbuilder also having that
as the minimum supported compiler version.
## 2.7.2 (2017-02-16)
* Fix a missing findlib toploop package (#61 from Vincent Bernardoff)
## 2.7.1 (2016-11-16)
* Use topkg for build (#60 from Jochen Bartl)
## 2.7.0 (2016-02-14)
* Remove `sexplib.syntax`, `type_conv` deps and camlp4 transitive dependency
* Add `ppx_sexp_conv` dependency
* Require OCaml 4.02.2+
* Add `Ipaddr.Prefix.subset`, `Ipaddr.V4.Prefix.subset` and `Ipaddr.V6.subset`
predicates to test containment of subnets (#52 from @seliopou)
## 2.6.1 (2015-02-20)
* Fix findlib requires in oasis to restore pre-4.02.1 compatibility
## 2.6.0 (2015-02-19)
* Change IPv6 link-local address prefix from fe80::/10 to fe80::/64. (#39)
* Remove type bytes = string alias (potentially breaking)
* Turn on -safe-string (#41)
* {V4,V6}.`to_bytes_raw` now uses Bytes.t rather than string (potentially breaking)
* Add multicast MAC conversions from RFC 1112 and RFC 2464
* Add `to_domain_name` conversions to DNS label lists (in-addr.arpa and ip6.arpa)
* Add `V6.interface_routers`, `V6.site_routers`, and `V6.Prefix.solicited_node`
* Add `V6.link_address_of_mac` to convert a MAC into a link local IP address
## 2.5.0 (2014-05-27)
* Add `with sexp` (de)serializers to all of the Ipaddr and Macaddr types. (#31)
## 2.4.0 (2014-02-11)
* Add `Ipaddr.V6.Prefix.of_netmask` for conversion from an IPv6
address/netmask to prefix (useful for some binary interfaces). See #27.
* Add `Ipaddr.V6.Prefix.netmask` to generate a netmask address from a
prefix (useful for some binary interfaces). See #27.
* Add `Ipaddr.Prefix.network` for generic prefix -> address conversion
* Add `Ipaddr.Prefix.netmask` for generic prefix -> netmask conversion
## 2.3.0 (2014-02-05)
* Add `Ipaddr.V4.Prefix.of_netmask` for conversion from an
address/netmask to prefix
* Add `Ipaddr.V4.Prefix.netmask` to generate a netmask address from a prefix
## 2.2.0 (2014-01-27)
* Add an [Ipaddr_unix] module to convert to-and-from the standard library.
* Add a toplevel pretty printer in the `ipaddr.top` package.
## 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
* Add type `scope` for classifying address scopes
* Add `Ipaddr.V4.of_string_raw` for parsing inside of larger strings
* Add `Ipaddr.V4.to_int16` and `Ipaddr.V4.of_int16`
* Add `unspecified`, `nodes`, and `routers` constants to `Ipaddr.V4`
* Add `Ipaddr.V4.Prefix.network_address` to put an address into a subnet
* Add `of_address_string_exn`, `of_address_string`, `to_address_string`,
`to_address_buffer` to `Ipaddr.V4.Prefix` to parse/print combined addr/prefix
* Add `multicast_org`, `multicast_admin`, `multicast_link` subnet constants to
`Ipaddr.V4.Prefix`
* Add `Ipaddr.V4.scope` to classify IPv4 addresses
* Add `Ipaddr.V4.is_global` and `Ipaddr.V4.is_multicast` predicates
* Add optional `sep:char` argument to `Macaddr.to_string`
* Remove internal use of Scanf.scanf
## 1.0.0 (2013-10-16)
* Add Travis-CI testing scripts.
* Include debug symbols and annot files by default.
## 0.2.3 (2013-09-20)
* Add `Ipaddr.V4.Prefix.bits` function to produce bits of prefix from prefix.
## 0.2.2 (2013-08-07)
* Add `Macaddr.make_local` function to create local unicast MAC
addresses from an octet generation function.
* Add `Macaddr.get_oui` accessor to extract the Organizationally Unique
Identifier as an integer.
* Add `Macaddr.is_local` predicate to test for a locally administered address.
* Add `Macaddr.is_unicast` predicate to test for a unicast MAC address.
## 0.2.1 (2013-08-01)
* Add `Ipaddr.V4.any`, `Ipaddr.V4.broadcast`, `Ipaddr.V4.localhost`
special constant addresses.
* Add `Ipaddr.V4.Prefix.global` (0.0.0.0/0) subnet constant.
* Add `Ipaddr.V4.Prefix.network` function to produce subnet address from prefix.
## 0.2.0 (2013-08-01)
* Add `Macaddr` module for handling MAC-48 (Ethernet) addresses.
* `Ipaddr.Parse_error` now contains both the error condition and the
failing input.
* Add ocamldoc-compatible comments on all interfaces.
## 0.1.1 (2013-07-31)
* Add loopback and link local addresses to the private blocks.
* Fix build system so Makefile is generated by OASIS.
## 0.1.0 (2013-07-24)
* Initial public release.
* Includes IPv4 and IPv4 CIDR prefix support.

View file

@ -0,0 +1,16 @@
ISC License
Copyright (c) 2013-2015 David Sheets <sheets@alum.mit.edu>
Copyright (c) 2010-2011, 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.

View file

@ -0,0 +1,13 @@
.PHONY: all clean
all:
dune build
test:
dune runtest
doc:
dune build @doc
clean:
dune clean

View file

@ -0,0 +1,64 @@
# ipaddr: IP and MAC address manipulation
A library for manipulation of IP and MAC address representations.
Features:
* ounit2-based tests
* IPv4 and IPv6 support
* IPv4 and IPv6 CIDR prefix support
* 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` and `Ipaddr.Prefix` modules are `Map.OrderedType`
* `Ipaddr_unix` in findlib subpackage `ipaddr.unix` provides compatibility with the standard library `Unix` module
* `Ipaddr_top` in findlib subpackage `ipaddr.top` provides top-level pretty printers
* 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`
* All types have sexplib serializers/deserializers optionally via the `Ipaddr_sexp` and `Macaddr_sexp` libraries.
## Usage
There are the following opam packages included:
- `ipaddr`: the `Ipaddr` and associated modules
- `ipaddr-sexp`
- `ipaddr-cstruct`
- `macaddr`: the `Macaddr` and associated modules.
- `macaddr-sexp`
- `macaddr-cstruct`
There are the following ocamlfind libraries included as part of this
repository, included as part of the respective opam packages.
- `ipaddr`: The `Ipaddr` module for IPv4/6 manipulation.
- `ipaddr.top`: Toplevel printers for Ipaddr.
- `ipaddr-cstruct`: The `Ipaddr_cstruct` module
- `macaddr`: The `Macaddr` module for MAC address manipulation.
- `macaddr.top`: Toplevel printers for Macaddr.
- `macaddr-cstruct`: The `Macaddr_cstruct` module
- `ipaddr-sexp`: S-expression converters for Ipaddr.
- `macaddr-sexp`: S-expression converters for Macaddr.
## Installation and development
The packages are released to the opam-repository. An `opam install ipaddr`
(or any other above mentioned package) will install it. If you want to install
the latest development commit, `opam pin add ipaddr --dev` will do this.
A local build, after a `git clone` can be done with `dune build`, a
`dune runtest` compiles and executes the testsuite. If dependencies are missing,
`opam install (-t) --deps-only .` in the cloned directory will install them.
The auto-formatter [`ocamlformat`](https://github.com/ocaml-ppx/ocamlformat) is
used, please execute `dune build @fmt --auto-promote` before submitting a pull
request.
## Contact
- Issues: <https://github.com/mirage/ocaml-ipaddr/issues>
- E-mail: <mirageos-devel@lists.xenproject.org>
- API Documentation: <http://docs.mirage.io/ipaddr/>
- Discussion: <https://discuss.ocaml.org> with the `mirageos` tag.

View file

@ -0,0 +1,5 @@
(lang dune 1.9)
(name ipaddr)
(version v5.6.1)
(allow_approximate_merlin)
(using fmt 1.1)

View file

@ -0,0 +1,26 @@
version: "5.6.1"
opam-version: "2.0"
maintainer: "anil@recoil.org"
authors: ["David Sheets" "Anil Madhavapeddy" "Hugo Heuzard"]
synopsis: "A library for manipulation of IP address representations using Cstructs"
license: "ISC"
tags: ["org:mirage" "org:xapi-project"]
homepage: "https://github.com/mirage/ocaml-ipaddr"
doc: "https://mirage.github.io/ocaml-ipaddr/"
bug-reports: "https://github.com/mirage/ocaml-ipaddr/issues"
depends: [
"ocaml" {>= "4.08.0"}
"dune" {>= "1.9.0"}
"ipaddr" {= version}
"cstruct" {>= "6.0.0"}
]
build: [
["dune" "subst"] {dev}
["dune" "build" "-p" name "-j" jobs]
["dune" "runtest" "-p" name "-j" jobs] {with-test}
]
dev-repo: "git+https://github.com/mirage/ocaml-ipaddr.git"
description: """
Cstruct convertions for macaddr
"""
x-maintenance-intent: [ "(latest)" ]

View file

@ -0,0 +1,30 @@
version: "5.6.1"
opam-version: "2.0"
maintainer: "anil@recoil.org"
authors: ["David Sheets" "Anil Madhavapeddy" "Hugo Heuzard"]
synopsis: "A library for manipulation of IP address representations using sexp"
description: """
Sexp convertions for ipaddr
"""
license: "ISC"
tags: ["org:mirage" "org:xapi-project"]
homepage: "https://github.com/mirage/ocaml-ipaddr"
doc: "https://mirage.github.io/ocaml-ipaddr/"
bug-reports: "https://github.com/mirage/ocaml-ipaddr/issues"
depends: [
"ocaml" {>= "4.08.0"}
"dune" {>= "1.9.0"}
"ipaddr" {= version}
"ipaddr-cstruct" {with-test & = version}
"ounit2" {with-test}
"ppx_sexp_conv" {>= "v0.9.0"}
"sexplib0"
]
build: [
["dune" "subst"] {dev}
["dune" "build" "-p" name "-j" jobs]
["dune" "runtest" "-p" name "-j" jobs] {with-test}
]
dev-repo: "git+https://github.com/mirage/ocaml-ipaddr.git"
x-maintenance-intent: [ "(latest)" ]

View file

@ -0,0 +1,44 @@
version: "5.6.1"
opam-version: "2.0"
maintainer: "anil@recoil.org"
authors: ["David Sheets" "Anil Madhavapeddy" "Hugo Heuzard"]
synopsis: "A library for manipulation of IP (and MAC) address representations"
description: """
Features:
* Depends only on sexplib (conditionalization under consideration)
* ounit2-based tests
* IPv4 and IPv6 support
* IPv4 and IPv6 CIDR prefix support
* 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` and `Ipaddr.Prefix` modules are `Map.OrderedType`
* `Ipaddr_unix` in findlib subpackage `ipaddr.unix` provides compatibility with the standard library `Unix` module
* `Ipaddr_top` in findlib subpackage `ipaddr.top` provides top-level pretty printers (requires compiler-libs default since OCaml 4.0)
* 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`
* All types have sexplib serializers/deserializers
"""
license: "ISC"
tags: ["org:mirage" "org:xapi-project"]
homepage: "https://github.com/mirage/ocaml-ipaddr"
doc: "https://mirage.github.io/ocaml-ipaddr/"
bug-reports: "https://github.com/mirage/ocaml-ipaddr/issues"
depends: [
"ocaml" {>= "4.08.0"}
"dune" {>= "1.9.0"}
"macaddr" {= version}
"domain-name" {>= "0.3.0"}
"ounit2" {with-test}
"ppx_sexp_conv" {with-test & >= "v0.9.0"}
]
build: [
["dune" "subst"] {dev}
["dune" "build" "-p" name "-j" jobs]
["dune" "runtest" "-p" name "-j" jobs] {with-test}
]
dev-repo: "git+https://github.com/mirage/ocaml-ipaddr.git"
x-maintenance-intent: [ "(latest)" ]

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@."

View file

@ -0,0 +1,48 @@
(rule
(copy# ../lib/ipaddr_sexp.ml ipaddr_sexp.ml))
(rule
(copy# ../lib/macaddr_sexp.ml macaddr_sexp.ml))
(rule
(copy# ../lib/ipaddr.ml ipaddr_internal.ml))
(library
(name test_macaddr_sexp)
(wrapped false)
(modules macaddr_sexp)
(preprocess
(pps ppx_sexp_conv))
(libraries macaddr sexplib0))
(library
(name test_ipaddr_sexp)
(wrapped false)
(modules ipaddr_sexp)
(preprocess
(pps ppx_sexp_conv))
(libraries ipaddr sexplib0))
(test
(name test_ipaddr)
(package ipaddr-sexp)
(modules test_ipaddr)
(libraries ipaddr ipaddr-cstruct test_ipaddr_sexp ounit2))
(test
(name test_ipaddr_b128)
(package ipaddr-sexp)
(modules test_ipaddr_b128 ipaddr_internal)
(libraries ipaddr ipaddr-cstruct test_ipaddr_sexp ounit2))
(test
(name test_macaddr)
(package macaddr-sexp)
(modules test_macaddr)
(libraries macaddr macaddr-cstruct test_macaddr_sexp ounit2))
(test
(name test_ppx)
(modules test_ppx)
(package ipaddr-sexp)
(libraries ipaddr macaddr test_ipaddr_sexp test_macaddr_sexp ounit2))

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,199 @@
(*
* Copyright (c) 2013-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.
*
*)
open OUnit
module B128 = Ipaddr_internal.S128
(* copied from test_ipaddr.ml *)
let assert_raises ~msg exn test_fn =
assert_raises ~msg exn (fun () ->
try test_fn ()
with rtexn ->
if exn <> rtexn then (
Printf.eprintf "Stacktrace for '%s':\n%!" msg;
Printexc.print_backtrace stderr);
raise rtexn)
let int_of_hex_char c =
match c with
| '0' .. '9' -> Char.code c - 48
| 'a' .. 'f' -> Char.code c - 87
| 'A' .. 'F' -> Char.code c - 55
| _ -> invalid_arg "char is not a valid hex digit"
let to_string (s : Ipaddr_internal.S128.t) =
let s : string = Obj.magic s in
List.init 16 (fun i -> Printf.sprintf "%.2x" (Char.code (String.get s i)))
|> String.concat ""
let of_string_exn s : B128.t =
if String.length s <> 32 then invalid_arg "not 32 chars long";
Bytes.init 16 (fun bi ->
let i = bi * 2 in
let x = int_of_hex_char s.[i + 1] and y = int_of_hex_char s.[i] in
char_of_int ((y lsl 4) + x))
|> Bytes.unsafe_to_string
|> Obj.magic
let assert_equal = assert_equal ~printer:to_string
let test_addition () =
(* simple addition *)
let d1 = B128.zero in
let d2 = of_string_exn "00000000000000000000000000000001" in
assert_equal ~msg:"adding one to zero is one" d2 (B128.add_exn d1 d2);
(* addition carry *)
let d1 = of_string_exn "000000000000000000ff000000000000" in
let d2 = of_string_exn "00000000000000000001000000000000" in
let d3 = of_string_exn "00000000000000000100000000000000" in
assert_equal ~msg:"test addition carry over" d3 (B128.add_exn d1 d2);
(* adding one to max_int overflows *)
let d1 = B128.max_int in
let d2 = of_string_exn "00000000000000000000000000000001" in
assert_raises ~msg:"adding one to max_int overflows" B128.Overflow (fun () ->
B128.add_exn d1 d2)
let test_pred () =
(* simple subtraction *)
let d1 = of_string_exn "00000000000000000000000000000001" in
let d2 = B128.zero in
assert_equal ~msg:"subtracting one from one is zero" d2 (B128.pred_exn d1);
(* subtract carry *)
let d1 = of_string_exn "00000000000000000000000000000300" in
let d2 = of_string_exn "000000000000000000000000000002ff" in
assert_equal ~msg:"test subtraction carry over" d2 (B128.pred_exn d1);
(* subtracting one from zero overflows *)
assert_raises ~msg:"subtracting one from min_int overflows" B128.Overflow
(fun () -> B128.pred_exn B128.zero)
let test_of_to_string () =
let s = "ff000000000000004200000000000001" in
OUnit.assert_equal ~msg:"input of of_string is equal to output of to_string" s
(of_string_exn s |> to_string)
let test_lognot () =
let d1 = of_string_exn "00000000000000000000000000000001" in
let d2 = of_string_exn "fffffffffffffffffffffffffffffffe" in
assert_equal ~msg:"lognot inverts bits" d2 (B128.lognot d1)
let test_shift_left () =
(* bit shift count, input, expected output *)
let test_shifts =
[
(1, "f0000000000000000000000000000000", "e0000000000000000000000000000000");
(1, "0000000000000000000000000000000f", "0000000000000000000000000000001e");
(1, "00000000000000000000000000000001", "00000000000000000000000000000002");
(2, "f0000000000000000000000000000000", "c0000000000000000000000000000000");
(2, "0000000000000000000000000000ffff", "0000000000000000000000000003fffc");
(8, "00000000000000000000000000000100", "00000000000000000000000000010000");
(9, "f0000000000000000000000000000000", "00000000000000000000000000000000");
( 64,
"00000000000000000000000000000001",
"00000000000000010000000000000000" );
( 127,
"00000000000000000000000000000001",
"80000000000000000000000000000000" );
( 128,
"00000000000000000000000000000001",
"00000000000000000000000000000000" );
]
in
List.iter
(fun (bits, input_value, expected_output) ->
assert_equal
~msg:(Printf.sprintf "shift left by %i" bits)
(of_string_exn expected_output)
(B128.shift_left (of_string_exn input_value) bits))
test_shifts
let test_shift_right () =
(* (bit shift count, input, expected output) *)
let test_shifts =
[
(1, "f0000000000000000000000000000000", "78000000000000000000000000000000");
(2, "f0000000000000000000000000000000", "3c000000000000000000000000000000");
(2, "0000000000000000000000000000ffff", "00000000000000000000000000003fff");
(2, "000000000000000000000000000ffff0", "0000000000000000000000000003fffc");
(8, "00000000000000000000000000000100", "00000000000000000000000000000001");
(9, "f0000000000000000000000000000000", "00780000000000000000000000000000");
( 32,
"000000000000000000000000ffffffff",
"00000000000000000000000000000000" );
( 32,
"0000000000000000aaaabbbbffffffff",
"000000000000000000000000aaaabbbb" );
( 40,
"0000000000000000aaaabbbbffffffff",
"00000000000000000000000000aaaabb" );
( 64,
"01000000000000000000000000000000",
"00000000000000000100000000000000" );
( 120,
"aaaabbbbccccdddd0000000000000000",
"000000000000000000000000000000aa" );
( 127,
"80000000000000000000000000000000",
"00000000000000000000000000000001" );
( 128,
"ffff0000000000000000000000000000",
"00000000000000000000000000000000" );
]
in
List.iter
(fun (bits, input_value, expected_output) ->
assert_equal
~msg:(Printf.sprintf "shift right by %i" bits)
(of_string_exn expected_output)
(B128.shift_right (of_string_exn input_value) bits))
test_shifts
let test_byte_module () =
let assert_equal = OUnit2.assert_equal ~printer:(Printf.sprintf "0x%x") in
assert_equal ~msg:"get 3 lsb" 0x00 (B128.Byte.get_lsbits 3 0x00);
assert_equal ~msg:"get 4 lsb" 0x0f (B128.Byte.get_lsbits 4 0xff);
assert_equal ~msg:"get 5 lsb" 0x10 (B128.Byte.get_lsbits 5 0x10);
assert_equal ~msg:"get 8 lsb" 0xff (B128.Byte.get_lsbits 8 0xff);
assert_equal ~msg:"get 3 msb" 0x0 (B128.Byte.get_msbits 3 0x00);
assert_equal ~msg:"get 4 msb" 0xf (B128.Byte.get_msbits 4 0xff);
assert_equal ~msg:"get 5 msb" 0x2 (B128.Byte.get_msbits 5 0x10);
assert_equal ~msg:"get 8 msb" 0xff (B128.Byte.get_msbits 8 0xff);
assert_equal ~msg:"set 3 msb" 0x20 (B128.Byte.set_msbits 3 0x1 0x00);
assert_equal ~msg:"set 4 msb" 0xa0 (B128.Byte.set_msbits 4 0xa 0x00);
assert_equal ~msg:"set 5 msb" 0x98 (B128.Byte.set_msbits 5 0x13 0x00);
assert_equal ~msg:"set 8 msb" 0xff (B128.Byte.set_msbits 8 0xff 0x00)
let suite =
"Test B128 module"
>::: [
"addition" >:: test_addition;
"pred" >:: test_pred;
"of_to_string" >:: test_of_to_string;
"lognot" >:: test_lognot;
"shift_left" >:: test_shift_left;
"shift_right" >:: test_shift_right;
"byte_module" >:: test_byte_module;
]
;;
let _results = run_test_tt_main suite in
()

View file

@ -0,0 +1,109 @@
(*
* Copyright (c) 2013-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.
*
*)
open OUnit
open Macaddr
let test_string_rt () =
let addrs = [ ("ca:fe:ba:be:ee:ee", ':'); ("ca-fe-ba-be-ee-ee", '-') ] in
List.iter
(fun (addr, sep) ->
let os = of_string_exn addr in
let ts = to_string ~sep os in
assert_equal ~msg:(addr ^ " <> " ^ ts) ts addr;
let os = Macaddr_sexp.(t_of_sexp (sexp_of_t os)) in
let ts = to_string ~sep os in
assert_equal ~msg:(addr ^ " <> " ^ ts) ts addr)
addrs
let assert_result_failure ~msg a =
match a with Ok _ -> assert_failure msg | Error (`Msg _) -> ()
let test_string_rt_bad () =
let addrs =
[
"ca:fe:ba:be:ee:e";
"ca:fe:ba:be:ee:eee";
"ca:fe:ba:be:eeee";
"ca:fe:ba:be:ee::ee";
"ca:fe:ba:be:e:eee";
"ca:fe:ba:be:ee-ee";
]
in
List.iter (fun addr -> assert_result_failure ~msg:addr (of_string addr)) addrs
let test_bytes_rt () =
let addr = "\254\099\003\128\000\000" in
assert_equal ~msg:(String.escaped addr) (to_octets (of_octets_exn addr)) addr
let test_bytes_rt_bad () =
let addrs = [ "\254\099\003\128\000"; "\254\099\003\128\000\000\233" ] in
List.iter
(fun addr ->
assert_result_failure ~msg:(String.escaped addr) (of_octets addr))
addrs
let test_cstruct_rt () =
let open Macaddr_cstruct in
let addr = "\254\099\003\128\000\000" in
assert_equal ~msg:(String.escaped addr)
(Cstruct.to_string (to_cstruct (of_cstruct_exn (Cstruct.of_string addr))))
addr
let error s = (s, Parse_error ("MAC is exactly 6 bytes", s))
let test_cstruct_rt_bad () =
let open Macaddr_cstruct in
let addrs =
[ error "\254\099\003\128\000"; error "\254\099\003\128\000\000\233" ]
in
List.iter
(fun (addr, exn) ->
assert_raises ~msg:(String.escaped addr) exn (fun () ->
of_cstruct_exn (Cstruct.of_string addr)))
addrs
let test_make_local () =
let () = Random.self_init () in
let bytegen i = if i = 0 then 253 else 255 - i in
let local_addr = make_local bytegen in
assert_equal ~msg:"is_local" (is_local local_addr) true;
assert_equal ~msg:"is_unicast" (is_unicast local_addr) true;
assert_equal ~msg:"localize" (to_octets local_addr).[0] (Char.chr 254);
for i = 1 to 5 do
assert_equal
~msg:("addr.[" ^ string_of_int i ^ "]")
(to_octets local_addr).[i]
(Char.chr (bytegen i))
done;
assert_equal ~msg:"get_oui" (get_oui local_addr)
((254 lsl 16) + (254 lsl 8) + 253)
let suite =
"Test"
>::: [
"string_rt" >:: test_string_rt;
"string_rt_bad" >:: test_string_rt_bad;
"bytes_rt" >:: test_bytes_rt;
"bytes_rt_bad" >:: test_bytes_rt_bad;
"cstruct_rt" >:: test_cstruct_rt;
"cstruct_rt_bad" >:: test_cstruct_rt_bad;
"make_local" >:: test_make_local;
]
;;
run_test_tt_main suite

View file

@ -0,0 +1,28 @@
(*
* 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.
*
*)
type t = {
ip : Ipaddr_sexp.t;
ipv6 : Ipaddr_sexp.V6.t;
ipv6p : Ipaddr_sexp.V6.Prefix.t;
ipv4 : Ipaddr_sexp.V4.t;
ipv4p : Ipaddr_sexp.V4.Prefix.t;
scope : Ipaddr_sexp.scope;
mac : Macaddr_sexp.t;
ipp : Ipaddr_sexp.Prefix.t;
}
[@@deriving sexp]

View file

@ -0,0 +1,26 @@
version: "5.6.1"
opam-version: "2.0"
maintainer: "anil@recoil.org"
authors: ["David Sheets" "Anil Madhavapeddy" "Hugo Heuzard"]
synopsis: "A library for manipulation of MAC address representations using Cstructs"
license: "ISC"
tags: ["org:mirage" "org:xapi-project"]
homepage: "https://github.com/mirage/ocaml-ipaddr"
doc: "https://mirage.github.io/ocaml-ipaddr/"
bug-reports: "https://github.com/mirage/ocaml-ipaddr/issues"
depends: [
"ocaml" {>= "4.08.0"}
"dune" {>= "1.9.0"}
"macaddr" {= version}
"cstruct" {>= "6.0.0"}
]
build: [
["dune" "subst"] {dev}
["dune" "build" "-p" name "-j" jobs]
["dune" "runtest" "-p" name "-j" jobs] {with-test}
]
dev-repo: "git+https://github.com/mirage/ocaml-ipaddr.git"
description: """
Cstruct convertions for macaddr
"""
x-maintenance-intent: [ "(latest)" ]

View file

@ -0,0 +1,30 @@
version: "5.6.1"
opam-version: "2.0"
maintainer: "anil@recoil.org"
authors: ["David Sheets" "Anil Madhavapeddy" "Hugo Heuzard"]
synopsis: "A library for manipulation of MAC address representations using sexp"
license: "ISC"
tags: ["org:mirage" "org:xapi-project"]
homepage: "https://github.com/mirage/ocaml-ipaddr"
doc: "https://mirage.github.io/ocaml-ipaddr/"
bug-reports: "https://github.com/mirage/ocaml-ipaddr/issues"
depends: [
"ocaml" {>= "4.08.0"}
"dune" {>= "1.9.0"}
"macaddr" {= version}
"macaddr-cstruct" {with-test & = version}
"ounit2" {with-test}
"ppx_sexp_conv" {>= "v0.9.0"}
"sexplib0"
]
conflicts: [ "ipaddr" {< "3.0.0"} ]
build: [
["dune" "subst"] {dev}
["dune" "build" "-p" name "-j" jobs]
["dune" "runtest" "-p" name "-j" jobs] {with-test}
]
dev-repo: "git+https://github.com/mirage/ocaml-ipaddr.git"
description: """
Sexp convertions for macaddr
"""
x-maintenance-intent: [ "(latest)" ]

View file

@ -0,0 +1,34 @@
version: "5.6.1"
opam-version: "2.0"
maintainer: "anil@recoil.org"
authors: ["David Sheets" "Anil Madhavapeddy" "Hugo Heuzard"]
synopsis: "A library for manipulation of MAC address representations"
license: "ISC"
tags: ["org:mirage" "org:xapi-project"]
homepage: "https://github.com/mirage/ocaml-ipaddr"
doc: "https://mirage.github.io/ocaml-ipaddr/"
bug-reports: "https://github.com/mirage/ocaml-ipaddr/issues"
depends: [
"ocaml" {>= "4.08.0"}
"dune" {>= "1.9.0"}
"ounit2" {with-test}
"ppx_sexp_conv" {with-test & >= "v0.9.0"}
]
conflicts: [ "ipaddr" {< "3.0.0"} ]
build: [
["dune" "subst"] {dev}
["dune" "build" "-p" name "-j" jobs]
["dune" "runtest" "-p" name "-j" jobs] {with-test}
]
dev-repo: "git+https://github.com/mirage/ocaml-ipaddr.git"
description: """
A library for manipulation of MAC address representations.
Features:
* ounit2-based tests
* MAC-48 (Ethernet) address support
* `Macaddr` is a `Map.OrderedType`
* All types have sexplib serializers/deserializers optionally via the `Macaddr_sexp` library.
"""
x-maintenance-intent: [ "(latest)" ]