1. james woodyatt
  2. oni

Commits

jhwoodyatt  committed fe23cdc

Initial commit of OCaml NAE "Network Extensions" library, composed by
transposing the relevant portions of Cf-0.9, i.e. those specifically
involved in extending the networking API.

  • Participants
  • Parent commits f68f6ab
  • Branches default

Comments (0)

Files changed (68)

File nx/.depend

View file
+nx_common_p.o: nx_common_p.c nx_common_p.h \
+  /usr/local/lib/ocaml/caml/alloc.h \
+  /usr/local/lib/ocaml/caml/compatibility.h \
+  /usr/local/lib/ocaml/caml/misc.h /usr/local/lib/ocaml/caml/config.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h \
+  /usr/local/lib/ocaml/caml/callback.h /usr/local/lib/ocaml/caml/custom.h \
+  /usr/local/lib/ocaml/caml/fail.h /usr/local/lib/ocaml/caml/intext.h \
+  /usr/local/lib/ocaml/caml/memory.h /usr/local/lib/ocaml/caml/misc.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h
+nx_socket_p.o: nx_socket_p.c nx_socket_p.h nx_common_p.h \
+  /usr/local/lib/ocaml/caml/alloc.h \
+  /usr/local/lib/ocaml/caml/compatibility.h \
+  /usr/local/lib/ocaml/caml/misc.h /usr/local/lib/ocaml/caml/config.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h \
+  /usr/local/lib/ocaml/caml/callback.h /usr/local/lib/ocaml/caml/custom.h \
+  /usr/local/lib/ocaml/caml/fail.h /usr/local/lib/ocaml/caml/intext.h \
+  /usr/local/lib/ocaml/caml/memory.h /usr/local/lib/ocaml/caml/misc.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h
+nx_netif_p.o: nx_netif_p.c nx_netif_p.h nx_common_p.h \
+  /usr/local/lib/ocaml/caml/alloc.h \
+  /usr/local/lib/ocaml/caml/compatibility.h \
+  /usr/local/lib/ocaml/caml/misc.h /usr/local/lib/ocaml/caml/config.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h \
+  /usr/local/lib/ocaml/caml/callback.h /usr/local/lib/ocaml/caml/custom.h \
+  /usr/local/lib/ocaml/caml/fail.h /usr/local/lib/ocaml/caml/intext.h \
+  /usr/local/lib/ocaml/caml/memory.h /usr/local/lib/ocaml/caml/misc.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h
+nx_nameinfo_p.o: nx_nameinfo_p.c nx_nameinfo_p.h nx_socket_p.h \
+  nx_common_p.h /usr/local/lib/ocaml/caml/alloc.h \
+  /usr/local/lib/ocaml/caml/compatibility.h \
+  /usr/local/lib/ocaml/caml/misc.h /usr/local/lib/ocaml/caml/config.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h \
+  /usr/local/lib/ocaml/caml/callback.h /usr/local/lib/ocaml/caml/custom.h \
+  /usr/local/lib/ocaml/caml/fail.h /usr/local/lib/ocaml/caml/intext.h \
+  /usr/local/lib/ocaml/caml/memory.h /usr/local/lib/ocaml/caml/misc.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h
+nx_sock_dgram_p.o: nx_sock_dgram_p.c nx_sock_dgram_p.h nx_socket_p.h \
+  nx_common_p.h /usr/local/lib/ocaml/caml/alloc.h \
+  /usr/local/lib/ocaml/caml/compatibility.h \
+  /usr/local/lib/ocaml/caml/misc.h /usr/local/lib/ocaml/caml/config.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h \
+  /usr/local/lib/ocaml/caml/callback.h /usr/local/lib/ocaml/caml/custom.h \
+  /usr/local/lib/ocaml/caml/fail.h /usr/local/lib/ocaml/caml/intext.h \
+  /usr/local/lib/ocaml/caml/memory.h /usr/local/lib/ocaml/caml/misc.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h
+nx_sock_stream_p.o: nx_sock_stream_p.c nx_sock_stream_p.h nx_socket_p.h \
+  nx_common_p.h /usr/local/lib/ocaml/caml/alloc.h \
+  /usr/local/lib/ocaml/caml/compatibility.h \
+  /usr/local/lib/ocaml/caml/misc.h /usr/local/lib/ocaml/caml/config.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h \
+  /usr/local/lib/ocaml/caml/callback.h /usr/local/lib/ocaml/caml/custom.h \
+  /usr/local/lib/ocaml/caml/fail.h /usr/local/lib/ocaml/caml/intext.h \
+  /usr/local/lib/ocaml/caml/memory.h /usr/local/lib/ocaml/caml/misc.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h
+nx_ip_common_p.o: nx_ip_common_p.c nx_ip_common_p.h nx_ip4_addr_p.h \
+  nx_common_p.h /usr/local/lib/ocaml/caml/alloc.h \
+  /usr/local/lib/ocaml/caml/compatibility.h \
+  /usr/local/lib/ocaml/caml/misc.h /usr/local/lib/ocaml/caml/config.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h \
+  /usr/local/lib/ocaml/caml/callback.h /usr/local/lib/ocaml/caml/custom.h \
+  /usr/local/lib/ocaml/caml/fail.h /usr/local/lib/ocaml/caml/intext.h \
+  /usr/local/lib/ocaml/caml/memory.h /usr/local/lib/ocaml/caml/misc.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h nx_ip6_addr_p.h nx_socket_p.h
+nx_ip4_addr_p.o: nx_ip4_addr_p.c nx_ip4_addr_p.h nx_common_p.h \
+  /usr/local/lib/ocaml/caml/alloc.h \
+  /usr/local/lib/ocaml/caml/compatibility.h \
+  /usr/local/lib/ocaml/caml/misc.h /usr/local/lib/ocaml/caml/config.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h \
+  /usr/local/lib/ocaml/caml/callback.h /usr/local/lib/ocaml/caml/custom.h \
+  /usr/local/lib/ocaml/caml/fail.h /usr/local/lib/ocaml/caml/intext.h \
+  /usr/local/lib/ocaml/caml/memory.h /usr/local/lib/ocaml/caml/misc.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h
+nx_ip6_addr_p.o: nx_ip6_addr_p.c nx_ip6_addr_p.h nx_common_p.h \
+  /usr/local/lib/ocaml/caml/alloc.h \
+  /usr/local/lib/ocaml/caml/compatibility.h \
+  /usr/local/lib/ocaml/caml/misc.h /usr/local/lib/ocaml/caml/config.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h \
+  /usr/local/lib/ocaml/caml/callback.h /usr/local/lib/ocaml/caml/custom.h \
+  /usr/local/lib/ocaml/caml/fail.h /usr/local/lib/ocaml/caml/intext.h \
+  /usr/local/lib/ocaml/caml/memory.h /usr/local/lib/ocaml/caml/misc.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h nx_ip4_addr_p.h
+nx_ip4_proto_p.o: nx_ip4_proto_p.c nx_ip4_proto_p.h nx_ip_common_p.h \
+  nx_ip4_addr_p.h nx_common_p.h /usr/local/lib/ocaml/caml/alloc.h \
+  /usr/local/lib/ocaml/caml/compatibility.h \
+  /usr/local/lib/ocaml/caml/misc.h /usr/local/lib/ocaml/caml/config.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h \
+  /usr/local/lib/ocaml/caml/callback.h /usr/local/lib/ocaml/caml/custom.h \
+  /usr/local/lib/ocaml/caml/fail.h /usr/local/lib/ocaml/caml/intext.h \
+  /usr/local/lib/ocaml/caml/memory.h /usr/local/lib/ocaml/caml/misc.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h nx_ip6_addr_p.h nx_socket_p.h
+nx_ip6_proto_p.o: nx_ip6_proto_p.c nx_ip6_proto_p.h nx_ip_common_p.h \
+  nx_ip4_addr_p.h nx_common_p.h /usr/local/lib/ocaml/caml/alloc.h \
+  /usr/local/lib/ocaml/caml/compatibility.h \
+  /usr/local/lib/ocaml/caml/misc.h /usr/local/lib/ocaml/caml/config.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h \
+  /usr/local/lib/ocaml/caml/callback.h /usr/local/lib/ocaml/caml/custom.h \
+  /usr/local/lib/ocaml/caml/fail.h /usr/local/lib/ocaml/caml/intext.h \
+  /usr/local/lib/ocaml/caml/memory.h /usr/local/lib/ocaml/caml/misc.h \
+  /usr/local/lib/ocaml/caml/mlvalues.h nx_ip6_addr_p.h nx_socket_p.h
+nx_nameinfo.cmi: nx_socket.cmi 
+nx_sock_common.cmi: nx_socket.cmi 
+nx_sock_dgram.cmi: nx_socket.cmi nx_sock_common.cmi 
+nx_sock_stream.cmi: nx_socket.cmi nx_sock_common.cmi 
+nx_ip_common.cmi: nx_socket.cmi 
+nx_ip6_addr.cmi: nx_ip4_addr.cmi 
+nx_ip4_proto.cmi: nx_socket.cmi nx_ip4_addr.cmi 
+nx_ip6_proto.cmi: nx_socket.cmi nx_ip6_addr.cmi nx_ip4_addr.cmi 
+nx_tcp4_socket.cmi: nx_sock_stream.cmi nx_ip4_proto.cmi 
+nx_tcp6_socket.cmi: nx_sock_stream.cmi nx_ip6_proto.cmi 
+nx_udp4_socket.cmi: nx_sock_dgram.cmi nx_ip4_proto.cmi 
+nx_udp6_socket.cmi: nx_sock_dgram.cmi nx_ip6_proto.cmi 
+nx_uri.cmi: nx_ip4_addr.cmi 
+nx_socket.cmo: nx_socket.cmi 
+nx_socket.cmx: nx_socket.cmi 
+nx_netif.cmo: nx_netif.cmi 
+nx_netif.cmx: nx_netif.cmi 
+nx_nameinfo.cmo: nx_socket.cmi nx_nameinfo.cmi 
+nx_nameinfo.cmx: nx_socket.cmx nx_nameinfo.cmi 
+nx_sock_common.cmo: nx_socket.cmi nx_sock_common.cmi 
+nx_sock_common.cmx: nx_socket.cmx nx_sock_common.cmi 
+nx_sock_dgram.cmo: nx_socket.cmi nx_sock_common.cmi nx_sock_dgram.cmi 
+nx_sock_dgram.cmx: nx_socket.cmx nx_sock_common.cmx nx_sock_dgram.cmi 
+nx_sock_stream.cmo: nx_socket.cmi nx_sock_common.cmi nx_sock_stream.cmi 
+nx_sock_stream.cmx: nx_socket.cmx nx_sock_common.cmx nx_sock_stream.cmi 
+nx_ip_common.cmo: nx_socket.cmi nx_ip_common.cmi 
+nx_ip_common.cmx: nx_socket.cmx nx_ip_common.cmi 
+nx_ip4_addr.cmo: nx_ip4_addr.cmi 
+nx_ip4_addr.cmx: nx_ip4_addr.cmi 
+nx_ip6_addr.cmo: nx_ip4_addr.cmi nx_ip6_addr.cmi 
+nx_ip6_addr.cmx: nx_ip4_addr.cmx nx_ip6_addr.cmi 
+nx_ip4_proto.cmo: nx_socket.cmi nx_ip_common.cmi nx_ip4_addr.cmi \
+    nx_ip4_proto.cmi 
+nx_ip4_proto.cmx: nx_socket.cmx nx_ip_common.cmx nx_ip4_addr.cmx \
+    nx_ip4_proto.cmi 
+nx_ip6_proto.cmo: nx_socket.cmi nx_ip_common.cmi nx_ip6_addr.cmi \
+    nx_ip4_addr.cmi nx_ip6_proto.cmi 
+nx_ip6_proto.cmx: nx_socket.cmx nx_ip_common.cmx nx_ip6_addr.cmx \
+    nx_ip4_addr.cmx nx_ip6_proto.cmi 
+nx_tcp4_socket.cmo: nx_sock_stream.cmi nx_ip4_proto.cmi nx_tcp4_socket.cmi 
+nx_tcp4_socket.cmx: nx_sock_stream.cmx nx_ip4_proto.cmx nx_tcp4_socket.cmi 
+nx_tcp6_socket.cmo: nx_sock_stream.cmi nx_ip6_proto.cmi nx_tcp6_socket.cmi 
+nx_tcp6_socket.cmx: nx_sock_stream.cmx nx_ip6_proto.cmx nx_tcp6_socket.cmi 
+nx_udp4_socket.cmo: nx_sock_dgram.cmi nx_ip4_proto.cmi nx_udp4_socket.cmi 
+nx_udp4_socket.cmx: nx_sock_dgram.cmx nx_ip4_proto.cmx nx_udp4_socket.cmi 
+nx_udp6_socket.cmo: nx_sock_dgram.cmi nx_ip6_proto.cmi nx_udp6_socket.cmi 
+nx_udp6_socket.cmx: nx_sock_dgram.cmx nx_ip6_proto.cmx nx_udp6_socket.cmi 
+nx_poll.cmo: nx_poll.cmi 
+nx_poll.cmx: nx_poll.cmi 
+nx_uri.cmo: nx_ip4_addr.cmi nx_uri.cmi 
+nx_uri.cmx: nx_ip4_addr.cmx nx_uri.cmi 
+t/t_nx.cmo: nx_tcp6_socket.cmi nx_tcp4_socket.cmi nx_poll.cmi \
+    nx_ip_common.cmi nx_ip6_addr.cmi nx_ip4_addr.cmi 
+t/t_nx.cmx: nx_tcp6_socket.cmx nx_tcp4_socket.cmx nx_poll.cmx \
+    nx_ip_common.cmx nx_ip6_addr.cmx nx_ip4_addr.cmx 

File nx/CHANGES

View file
+===== OCaml NAE Network Extensions (Nx) library =====
+
+This file describes in technical detail the functional differences between
+released versions of the library.
+
+
+===== Version 0.0 =====
+
+This was the initial release of the library, produced by copying the source
+code from the Cf library and transposing all the names to Nx.
+
+Major and minor version numbers count upward from zero.  Major version numbers
+with a minor version number of zero indicate the first release in a "stable"
+branch.  Non-zero minor version numbers indicate "development" branches
+converging on the next stable release.  Patches to stable releases are numbered
+with a third level of numbering.
+
+
+--j h woodyatt <jhw@conjury.org>

File nx/ISSUES

View file
+Open issues in development:
+
++ (unspecified): A GODI package would be nice to promote community adoption.
+
++ (Nx_poll): Alan Post writes:
+
+  "When converting [Nx_poll] to use kqueue, I noticed that even after
+  this conversion, the operations don't always scale that well:
+
+               load      unload     service
+    fd         lg n      lg n       lg n
+    timer      C         n          C
+    idle       C         n          C
+
+  In each case, the "n" is the number of registered callbacks of the
+  particular type.
+
+  The signal callbacks are limited to one per signal slot, so scaling
+  isn't really an applicable issue at the moment.  I didn't address
+  that limitation in [Nx_poll] as a part of the kqueue patch because the
+  issues were unrelated.
+
+  In the same vein, [nx_poll] currently allows only one callback per fd;
+  this seems sensible to me, but should probably be documented."
+
++ (Nx_socket_p): No support for WIN32.  SVR4 remains untested, but portability
+    has been substantially improved.  Suse Linux 9.0+ may still work.  I don't
+    know anymore, since my Linux box died, I replaced it with Mac OS X
+    Server 10.4, and I haven't looked back.
+
++ (Nx_socket and cognates): Support for sendmsg() and recvmsg(), and associated
+    IPv4 and IPv6 protocol options that use the control plane for various
+    advanced features of the network protocol stack.
+
++ (Nx_socket and cognates): Support for AF_LOCAL.  To do this right, we need
+    support for the control plane using sendmsg() and recvmsg(), so we can have
+    file descriptor and user credential passing-- pretty much the only good
+    reasons to use AF_LOCAL other than to communicate with other programs that
+    use them instead of AF_INET on the loopback interface for no good reason.
+
++ (Nx_nameinfo): There should be a function for acquiring an 'en-US' localized
+    string corresponding to a value of type [unresolved].
+
+# End of open issues

File nx/LICENSE

View file
+  Copyright (c) 2007, James H. Woodyatt
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+    Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+  OF THE POSSIBILITY OF SUCH DAMAGE. 

File nx/META

View file
+# The following META file is a guess by ocamlfind:
+name="nx"
+version="0.0"
+description="OCaml NAE Network Extensions"
+requires="unix cf"
+archive(byte)="nx.cma"
+archive(native)="nx.cmxa"

File nx/Makefile

View file
+# FILE     Makefile
+#
+# Copyright (c) 2007, James H. Woodyatt
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#   Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+#
+#   Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in
+#   the documentation and/or other materials provided with the
+#   distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE. 
+
+REQUIRE = unix cf
+PREDICATES =
+
+###############################################################################
+
+.PHONY: default opt test test.opt clean install uninstall depend doc
+
+default::
+
+#OCAMLFINDOPT = -pp camlp4o -package "$(REQUIRE)" -predicates "$(PREDICATES)"
+#OCAMLDEP = ocamldep -pp camlp4o
+
+OCAMLFINDOPT = -package "$(REQUIRE)" -predicates "$(PREDICATES)"
+
+OCAMLC       = ocamlfind ocamlc $(OCAMLFINDOPT)
+OCAMLOPT     = ocamlfind ocamlopt $(OCAMLFINDOPT)
+OCAMLMKLIB   = ocamlmklib
+OCAMLMKTOP   = ocamlfind ocamlmktop $(OCAMLFINDOPT)
+OCAMLDEP     = ocamldep
+OCAMLLEX     = ocamllex
+OCAMLYACC    = ocamlyacc
+OCAMLDOC     = ocamlfind ocamldoc $(OCAMLFINDOPT)
+
+DEBUG_OPT    = -g
+WARN_ERROR   = -passopt -w -passopt Ae # -warn-error A
+PRINCIPLE    = -principal
+UNSAFE       = -unsafe -noassert
+
+ALL_OCAML_OPT = $(WARN_ERROR) $(PRINCIPLE)
+
+CC_OPT  = -ccopt -fPIC -ccopt -O2 -ccopt -Wall -ccopt -Wno-unused-variable
+# add "-ccopt -I/usr/local/include -ccopt -L/usr/local/lib" for FreeBSD 6.2
+CMI_OPT = $(ALL_OCAML_OPT) $(DEBUG_OPT)
+CMO_OPT = $(ALL_OCAML_OPT) $(DEBUG_OPT)
+CMX_OPT = $(ALL_OCAML_OPT) $(UNSAFE) -inline 9
+
+.SUFFIXES: .ml .mli .mll .mly .cmo .cmi .cma .cmx .cmxa
+
+%.ml : %.mll
+	$(OCAMLLEX) $<
+
+%.ml %.mli : %.mly
+	$(OCAMLYACC) -b$* $<
+
+%.cmi : %.mli
+	$(OCAMLC) $(CMI_OPT) -o $@ -c $<
+
+%.cmi %.cmo : %.ml
+	$(OCAMLC) $(CMO_OPT) -o $@ -c $<
+
+%.cmi %.cmx %.o : %.ml
+	$(OCAMLOPT) $(CMX_OPT) -o $@ -c $<
+
+%.o : %.c
+	$(OCAMLC) $(CC_OPT) -o $@ -c $<
+
+clean::
+	rm -f *.cmi *.cmo *.cma
+	rm -f *.cmx *.cmxa *.o *.a dll*.so
+
+###############################################################################
+
+default:: nx.cma
+
+opt:: nx.cmxa
+
+NX_LEXYACC_MODULES =
+
+NX_YACC_MODULES = $(NX_LEXYACC_MODULES:%=nx_yacc_%)
+NX_LEX_MODULES = $(NX_LEXYACC_MODULES:%=nx_lex_%)
+
+#clean::
+#	rm -rf $(NX_LEX_ML_FILES)
+#	rm -rf $(NX_YACC_ML_FILES)
+#	rm -rf $(NX_YACC_MLI_FILES)
+
+nx_lex_%.cmo : nx_yacc_%.cmi nx_lex_%.cmi
+nx_lex_%.cmx : nx_yacc_%.cmi nx_lex_%.cmi
+
+#manual dependencies
+
+#nx_yacc_foo.cmi: nx_foo_bar.cmi
+#nx_lex_foo.cmi: nx_foo_bar.cmi
+
+NX_LEX_ML_FILES = $(NX_LEX_MODULES:%=%.ml)
+NX_YACC_ML_FILES = $(NX_YACC_MODULES:%=%.ml)
+NX_YACC_MLI_FILES = $(NX_YACC_MODULES:%=%.mli)
+
+NX_ADDR_MODULES = ip4 ip6
+NX_PROTO_MODULES = ip4 ip6
+
+NX_MODULES = \
+    socket netif nameinfo sock_common sock_dgram sock_stream \
+	ip_common $(NX_ADDR_MODULES:%=%_addr) $(NX_PROTO_MODULES:%=%_proto) \
+    tcp4_socket tcp6_socket udp4_socket udp6_socket poll uri
+
+NX_PRIMITIVES = \
+    common socket netif nameinfo sock_dgram sock_stream ip_common \
+	$(NX_ADDR_MODULES:%=%_addr) $(NX_PROTO_MODULES:%=%_proto)
+
+NX_ML_FILES = $(NX_MODULES:%=nx_%.ml)
+NX_MLI_FILES = $(NX_MODULES:%=nx_%.mli)
+NX_CMI_FILES = $(NX_MODULES:%=nx_%.cmi)
+NX_CMO_FILES = $(NX_MODULES:%=nx_%.cmo)
+NX_CMX_FILES = $(NX_MODULES:%=nx_%.cmx)
+NX_O_FILES = $(NX_MODULES:%=nx_%.o)
+
+NX_P_C_FILES = $(NX_PRIMITIVES:%=nx_%_p.c)
+NX_P_H_FILES = $(NX_PRIMITIVES:%=nx_%_p.h)
+NX_P_O_FILES = $(NX_PRIMITIVES:%=nx_%_p.o)
+
+libnx.a dllnx.so : $(NX_P_O_FILES) # $(NX_CMI_FILES) $(NX_CMO_FILES)
+	$(OCAMLMKLIB) -o nx $(NX_P_O_FILES)
+
+nx.cma : libnx.a dllnx.so $(NX_CMI_FILES) $(NX_CMO_FILES)
+	$(OCAMLMKLIB) -o nx $(NX_CMO_FILES) -lnx
+
+nx.cmxa nx.a : libnx.a dllnx.so $(NX_CMI_FILES) $(NX_CMX_FILES) $(NX_O_FILES)
+	$(OCAMLMKLIB) -o nx $(NX_CMX_FILES) -lnx
+
+install:: libnx.a dllnx.so nx.cma
+	{ test ! -f nx.cmxa || extra="nx.cmxa nx.a"; }; \
+	ocamlfind install nx \
+	  $(NX_MLI_FILES) $(NX_CMI_FILES) $(NX_P_H_FILES) \
+          nx.cma libnx.a dllnx.so META $$extra
+
+uninstall::
+	ocamlfind remove nx
+
+###############################################################################
+
+TEST_MODULES = nx # setbench deq
+
+TEST_PROGRAMS = $(TEST_MODULES:%=t.%)
+TEST_OPT_PROGRAMS = $(TEST_MODULES:%=t-opt.%)
+
+TEST_ML_FILES = $(TEST_MODULES:%=t/t_%.ml)
+
+TEST_LINKOPT = -cclib -L. -linkpkg
+TEST_LIBS = nx
+
+default:: $(TEST_PROGRAMS)
+
+opt:: $(TEST_OPT_PROGRAMS)
+
+t.% : t/t_%.ml $(TEST_LIBS:%=%.cma)
+	$(OCAMLC) -o $@ $(CMO_OPT) $(DEBUG_OPT) $(TEST_LINKOPT) \
+        $(TEST_LIBS:%=%.cma) $<
+
+t-opt.% : t/t_%.ml $(TEST_LIBS:%=%.cmxa)
+	$(OCAMLOPT) -o $@ $(CMX_OPT) $(TEST_LINKOPT) $(TEST_LIBS:%=%.cmxa) $<
+
+test:: $(TEST_PROGRAMS)
+	@for i in $(TEST_PROGRAMS); do \
+	    echo; \
+	    echo $$i; \
+	    CAML_LD_LIBRARY_PATH=. ./$$i; \
+	done
+
+test.opt:: $(TEST_OPT_PROGRAMS)
+	@for i in $(TEST_OPT_PROGRAMS); do \
+	    echo; \
+	    echo $$i; \
+	    CAML_LD_LIBRARY_PATH=. ./$$i; \
+	done
+
+clean::
+	rm -f t/*.cmi t/*.cmo
+	rm -f t/*.cmx t/*.o
+	rm -f t.* t-opt.*
+
+###############################################################################
+
+default:: ocamltop
+
+ocamltop: $(TEST_LIBS:%=%.cma)
+	$(OCAMLMKTOP) -o $@ $(CMO_OPT) $(TEST_LINKOPT) $(TEST_LIBS:%=%.cma)
+
+clean::
+	rm -f ocamltop
+
+###############################################################################
+
+DOC_SOURCES = $(NX_MLI_FILES) $(NX_ML_FILES)
+
+DOC_INCLUDE_CF = `ocamlfind query cf`
+
+doc::
+	@mkdir -p doc
+	$(OCAMLDOC) -v -d doc -html -colorize-code -m A $(DOC_SOURCES)
+	
+#	$(OCAMLDOC) -v -d doc -html -colorize-code -m A \
+#		-I $(DOC_INCLUDE_CF) $(DOC_SOURCES)
+
+###############################################################################
+
+DEPEND_FILE=.depend
+
+$(DEPEND_FILE) ::
+	$(OCAMLC) -c -ccopt -MM $(NX_P_C_FILES) > .depend
+	$(OCAMLDEP) $(NX_MLI_FILES) $(NX_ML_FILES) $(TEST_ML_FILES) >> .depend
+
+depend:: $(DEPEND_FILE)
+
+include $(DEPEND_FILE)
+
+# End of file [ Makefile ]

File nx/README

View file
+===== OCaml NAE Network Extensions (nx) library =====
+
+This distribution is the Objective Caml Network Application Environment (NAE)
+"Network Extensions" library, which is a set of low-level interfaces designed
+for advanced network programming.
+
+Highlights include...
+
+- Extended socket interface (supports more options, and UDP w/multicast).
+- I/O event multiplexing (with Unix.select).
+
+Note: see the ISSUES file for a list of open problems in this release.
+
+===== Required Components =====
+
+This library requires the following external components:
+
+- Objective Caml (v3.10.0 or newer)
+- Findlib (tested with v1.1.2p1)
+- OCaml NAE Core Foundation (cf-0.9)
+
+Principal development was on Mac OS X 10.4 w/ XCode 2.4.1 using GCC 4.0.  Other
+platforms with POSIX-like environments should require a minimal porting effort.
+
+One major open issue: the extended socket interface is broken under WIN32.
+(The author invites help porting the library to other environments.)
+
+===== Building =====
+
+No 'configure' script is provided.  Compile the library with:
+
+    $ make default
+
+Compile both bytecode and native versions with:
+
+    $ make default opt
+
+Execute tests for byte and native versions with:
+
+    $ make test test.opt
+
+Install the library with ocamlfind using:
+
+    $ make install
+
+Uninstall the library with ocamlfind using:
+
+    $ make uninstall
+
+Make the reference documentation with ocamldoc using:
+
+    $ make doc
+
+
+--j h woodyatt <jhw@conjury.org>
+  San Francisco, CA

File nx/nx_common_p.c

View file
+/*---------------------------------------------------------------------------*
+  C MODULE  nx_common_p.c
+
+  Copyright (c) 2002-2006, James H. Woodyatt
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+    Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+  OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *---------------------------------------------------------------------------*/
+
+#include "nx_common_p.h"
+
+value nx_get_constant(const Nx_constant_table_t* tablePtr, int n)
+{
+    const int* arrayPtr = tablePtr->array;
+    unsigned int size = arrayPtr ? tablePtr->size : 0;
+    unsigned int i;
+    
+    for (i = 0; i < size; ++i) {
+        if (arrayPtr[i] == n)
+            return (Val_int(i));
+    }
+    
+    return tablePtr->unknown(n);
+}
+
+/*--- End of File [ nx_common_p.c ] ---*/

File nx/nx_common_p.h

View file
+/*---------------------------------------------------------------------------*
+  C HEADER  nx_common_p.h
+
+  Copyright (c) 2002-2006, James H. Woodyatt
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+    Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+  OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *---------------------------------------------------------------------------*/
+
+#ifndef _NX_COMMON_P_H
+#define _NX_COMMON_P_H
+
+#include <caml/alloc.h>
+#include <caml/callback.h>
+#include <caml/custom.h>
+#include <caml/fail.h>
+#include <caml/intext.h>
+#include <caml/memory.h>
+#include <caml/misc.h>
+#include <caml/mlvalues.h>
+
+CAMLextern void enter_blocking_section(void);
+CAMLextern void leave_blocking_section(void);
+
+typedef value (*Nx_const_constructor_f)(int n);
+
+struct nx_constant_table_s {
+    const int*			array;
+    unsigned int		size;
+    Nx_const_constructor_f	unknown;
+};
+
+typedef struct nx_constant_table_s Nx_constant_table_t;
+
+extern value nx_get_constant(const Nx_constant_table_t* tablePtr, int n);
+
+#define Nothing		((value) 0)
+
+/*--- These are imported from the unix library in the ocaml distro ---*/
+extern void unix_error(int code, const char fname[], value arg) Noreturn;
+extern void uerror(const char* fname, value arg) Noreturn;
+
+#endif /* defined(_NX_COMMON_P_H) */
+
+/*--- End of File [ nx_common_p.h ] ---*/

File nx/nx_ip4_addr.ml

View file
+(*---------------------------------------------------------------------------*
+  IMPLEMENTATION  nx_ip4_addr.ml
+
+  Copyright (c) 2003-2006, James H. Woodyatt
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+    Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+  OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *---------------------------------------------------------------------------*)
+
+external init_: unit -> unit = "nx_ip4_addr_init";;
+init_ ();;
+
+type -'a t
+
+type opaque = [ `AF_INET ]
+
+type category = Unspecified | Unicast | Multicast | Experimental | Broadcast
+
+type unspecified = [ opaque | `X ]
+type unicast = [ opaque | `U ]
+type multicast = [ opaque | `M ]
+type experimental = [ opaque | `E ]
+type broadcast = [ opaque | `B ]
+
+external category: opaque t -> category = "nx_ip4_addr_category"
+external is_unicast: [> opaque ] t -> unicast t = "nx_ip4_addr_is_unicast"
+external is_multicast:
+    [> opaque ] t -> multicast t = "nx_ip4_addr_is_multicast"
+external is_experimental:
+    [> opaque ] t -> experimental t = "nx_ip4_addr_is_experimental"
+
+type unicast_realm = U_loopback | U_link | U_private | U_global
+external unicast_realm:
+    [> unicast ] t -> unicast_realm = "nx_ip4_addr_unicast_realm"
+
+type multicast_realm = M_link | M_global
+external multicast_realm:
+    [> multicast ] t -> multicast_realm = "nx_ip4_addr_multicast_realm"
+
+external any_: unit -> unspecified t = "nx_ip4_addr_any"
+external broadcast_: unit -> broadcast t = "nx_ip4_addr_broadcast"
+external loopback_: unit -> unicast t = "nx_ip4_addr_loopback"
+external empty_group_: unit -> multicast t = "nx_ip4_addr_empty_group"
+external all_hosts_group_: unit -> multicast t = "nx_ip4_addr_all_hosts_group"
+external all_routers_group_:
+    unit -> multicast t = "nx_ip4_addr_all_routers_group"
+
+let any = any_ ()
+let broadcast = broadcast_ ()
+let loopback = loopback_ ()
+let empty_group = empty_group_ ()
+let all_hosts_group = all_hosts_group_ ()
+let all_routers_group = all_routers_group_ ()
+
+external equal: ([> opaque ] t as 'a) -> 'a -> bool = "nx_ip4_addr_equal"
+external compare: ([> opaque ] t as 'a) -> 'a -> int =
+    "nx_ip4_addr_compare_aux"
+
+external pton: string -> opaque t option = "nx_inet_pton4"
+external ntop: [> opaque ] t -> string = "nx_inet_ntop4"
+
+external network_min_prefix_:
+    ([> opaque ] as 'a) t -> int = "nx_ip4_addr_network_min_prefix"
+
+external network_member_:
+    ([> opaque ] as 'a) t -> int -> 'a t -> bool =
+    "nx_ip4_addr_network_member"
+
+external network_limit_:
+    ([> opaque ] as 'a) t -> int -> int -> 'a t =
+    "nx_ip4_addr_network_limit"
+
+external network_next_: 'a t -> int -> 'a t = "nx_ip4_addr_network_next"
+
+external network_netmask_: int -> string = "nx_ip4_addr_network_netmask"
+    
+let rec iterator_ ~dir ~lim addr =
+    lazy begin
+        if equal addr lim then
+            Cf_seq.Z
+        else
+            Cf_seq.P (addr, iterator_ ~dir ~lim (network_next_ addr dir))
+    end
+
+type 'a network = {
+    net_prefix_: int;
+    net_minimum_: 'a t;
+    net_maximum_: 'a t;
+    net_member_: 'a t -> bool;
+} constraint 'a = [> opaque ]
+
+let net_create ?subnet:s n =
+    let p = match s with Some p -> p | None -> network_min_prefix_ n in {
+        net_prefix_ = p;
+        net_minimum_ = network_limit_ n p (-1);
+        net_maximum_ = network_limit_ n p 1;
+        net_member_ = fun x -> network_member_ n p x;
+    }
+
+let net_number net = net.net_minimum_
+let net_broadcast net = net.net_maximum_
+let net_prefix net = net.net_prefix_
+let net_member net = net.net_member_
+let net_mask net = network_netmask_ net.net_prefix_
+
+let net_increasing net =
+    iterator_ ~dir:1 ~lim:net.net_maximum_ net.net_minimum_
+
+let net_decreasing net =
+    iterator_ ~dir:(-1) ~lim:net.net_minimum_ net.net_maximum_
+
+(*--- End of File [ nx_ip4_addr.ml ] ---*)

File nx/nx_ip4_addr.mli

View file
+(*---------------------------------------------------------------------------*
+  INTERFACE  nx_ip4_addr.mli
+
+  Copyright (c) 2003-2006, James H. Woodyatt
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+    Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+  OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *---------------------------------------------------------------------------*)
+
+(** IPv4 addresses with attribute parameters for type safety.
+
+    This module implements IPv4 addresses in an abstract type suitable for use
+    with the {!Nx_nameinfo} module, the {!Nx_socket} module and its cognates
+    for IPv4 transports.  Internally, the IPv4 address is represented as a
+    boxed 4-byte custom block.  Externally, the IPv4 address abstract type is
+    parameterized with a shadow attribute that constrains how it may be used
+    depending on its address category.
+*)
+
+(** The type of IPv4 addresses, parameterized by address category attribute. *)
+type -'a t
+
+(** The shadow attribute type of IPv4 addresses of unknown category. *)
+type opaque = [ `AF_INET ]
+
+(** The IPv4 address category type. *)
+type category =
+    | Unspecified   (** 0.0.0.0 *)
+    | Unicast       (** 0.0.0.1 to 223.255.255.255 *)
+    | Multicast     (** 224.0.0.0 to 239.255.255.255 *)
+    | Experimental  (** 240.0.0.0 to 255.255.255.254 *)
+    | Broadcast     (** 255.255.255.255 *)
+
+(** The shadow attribute type of IPv4 addresses of the Unspecified category. *)
+type unspecified = [ opaque | `X ]
+
+(** The shadow attribute type of IPv4 addresses of the Unicast category. *)
+type unicast = [ opaque | `U ]
+
+(** The shadow attribute type of IPv4 addresses of the Multicast category. *)
+type multicast = [ opaque | `M ]
+
+(** The shadow attribute type of IPv4 addresses of the Experimental category.
+*)
+type experimental = [ opaque | `E ]
+
+(** The shadow attribute type of IPv4 addresses of the Broadcast category. *)
+type broadcast = [ opaque | `B ]
+
+(** Use [category a] to obtain the category of an opaque IPv4 address. *)
+val category: opaque t -> category
+
+(** Use [is_unicast a] to validate that an IPv4 address is a unicast address.
+    Raises [Failure] if the address is not a unicast address.
+*)
+val is_unicast: [> opaque ] t -> unicast t
+
+(** Use [is_multicast a] to validate that an IPv4 address is a multicast
+    address.  Raises [Failure] if the address is not a multicast address.
+*)
+val is_multicast: [> opaque ] t -> multicast t
+
+(** Use [is_experimental a] to validate that an IPv4 address is an experimental
+    address.  Raises [Failure] if the address is not an experimental address.
+*)
+val is_experimental: [> opaque ] t -> experimental t
+
+(** The type of unicast address realms. *)
+type unicast_realm =
+    | U_loopback    (** Loopback, i.e. 127/8 *)
+    | U_link        (** Link-local, i.e. 169.254/16 *)
+    | U_private     (** Private, i.e. 10/8, 172.16/12 and 192.168/16 *)
+    | U_global      (** Global, all other unicast addresses *)
+
+(** Use [unicast_realm a] to identify the address realm of the unicast address
+    [a].
+*)
+val unicast_realm: [> unicast ] t -> unicast_realm
+
+(** The type of multicast address realms. *)
+type multicast_realm = M_link | M_global
+
+(** Use [multicast realm a] to identify the address of the multicast address
+    [a].
+*)
+val multicast_realm: [> multicast ] t -> multicast_realm
+
+(** The unspecified IPv4 address, i.e. 0.0.0.0. *)
+val any: unspecified t
+
+(** The link-local broadcast IPv4 address, i.e. 255.255.255.255. *)
+val broadcast: broadcast t
+
+(** The default loopback host address, i.e. 127.0.0.1. *)
+val loopback: unicast t
+
+(** The empty group multicast address, i.e. 224.0.0.0. *)
+val empty_group: multicast t
+
+(** The all-hosts group multicast address, i.e. 224.0.0.1 *)
+val all_hosts_group: multicast t 
+
+(** The all-routers group multicast address, i.e. 224.0.0.2 *)
+val all_routers_group: multicast t
+
+(** Use [equal a1 a2] to compare two IPv4 addresses for equality. *)
+val equal: [> opaque ] t -> [> opaque ] t -> bool
+
+(** Use [compare a1 a2] to compare the ordinality of two IPv4 addresses. *)
+val compare: [> opaque ] t -> [> opaque ] t -> int
+
+(** Use [pton s] to convert the string [s] containing an IPv4 address in
+    dot-quad format to its equivalent opaque IPv4 address.  Returns [None] if
+    the string is not in dot-quad format.
+*)
+val pton: string -> opaque t option
+
+(** Use [ntop a] to obtain a string representation of the IPv4 address [a]
+    in dot-quad format. *)
+val ntop: [> opaque ] t -> string
+
+(** The type of an IPv4 network identifier. *)
+type 'a network constraint 'a = [> opaque ]
+
+(** Use [net_create ?subnet a] to create an IPv4 network identifier that
+    contains the address [a] in its logical scope, optional constraining the
+    network to subnetwork of width [subnet].
+*)
+val net_create: ?subnet:int -> ([> opaque ] as 'a) t -> 'a network
+
+(** Use [net_number n] to produce the IPv4 address conventionally used to
+    identify the network.
+*)
+val net_number: 'a network -> 'a t
+
+(** Use [net_broadcast n] to produce the IPv4 address conventionally used to
+    identify the broadcast address for the network or subnet.
+*)
+val net_broadcast: 'a network -> 'a t
+
+(** Use [net_prefix] to obtain the number of bits in the subnet mask. *)
+val net_prefix: 'a network -> int
+
+(** Use [net_member n a] to test whether the address [a] is in the scope of the
+    network [n].
+*)
+val net_member: 'a network -> 'a t -> bool
+
+(** Use [net_mask n] to return a string representation of the subnet mask for
+    the network [n] in traditional dot-quad format.
+*)
+val net_mask: 'a network -> string
+
+(** Use [net_increasing n] to obtain the sequence of unicast IPv4 addresses
+    belong to the network [n] in increasing order.
+*)
+val net_increasing: 'a network -> 'a t Cf_seq.t
+
+(** Use [net_decreasing n] to obtain the sequence of unicast IPv4 addresses
+    belong to the network [n] in decreasing order.
+*)
+val net_decreasing: 'a network -> 'a t Cf_seq.t
+
+(*--- End of File [ nx_ip4_addr.mli ] ---*)

File nx/nx_ip4_addr_p.c

View file
+/*---------------------------------------------------------------------------*
+  C MODULE  nx_ip4_addr_p.c
+
+  Copyright (c) 2003-2006, James H. Woodyatt
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+    Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+  OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *---------------------------------------------------------------------------*/
+
+#include "nx_ip4_addr_p.h"
+
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include <string.h>
+
+
+#define FAILWITH(S)	(failwith("Nx_ip4_addr." S))
+
+/*---------------------------------------------------------------------------*
+  IPv4 addresses
+ *---------------------------------------------------------------------------*/
+
+enum nx_ip4_addr_unicast_realm {
+    Nx_ip4_addr_U_loopback,
+    Nx_ip4_addr_U_link,
+    Nx_ip4_addr_U_private,
+    Nx_ip4_addr_U_global
+};
+
+enum nx_ip4_addr_multicast_realm {
+    Nx_ip4_addr_M_link,
+    Nx_ip4_addr_M_global
+};
+
+static int nx_ip4_addr_compare(value v1, value v2)
+{
+    CAMLparam2(v1, v2);
+    const u_int8_t* addr1Ptr;
+    const u_int8_t* addr2Ptr;
+    int i, result;
+    
+    addr1Ptr = (u_int8_t*)(&Nx_ip4_addr_val(v1)->s_addr) + 3;
+    addr2Ptr = (u_int8_t*)(&Nx_ip4_addr_val(v2)->s_addr) + 3;
+    
+    for (i = 4; i >= 0; --i, --addr1Ptr, --addr2Ptr) {
+        result = *addr1Ptr - *addr2Ptr;
+        if (result) break;
+    }
+    
+    CAMLreturn(result);
+}
+
+static long nx_ip4_addr_hash(value v)
+{
+    CAMLparam1(v);
+    long result;
+    
+    result = (long) ntohl(Nx_ip4_addr_val(v)->s_addr);
+    
+    CAMLreturn(result);
+}
+
+static void nx_ip4_addr_serialize
+   (value v, unsigned long* size32Ptr, unsigned long* size64Ptr)
+{
+    CAMLparam1(v);
+    
+    serialize_block_1(&Nx_ip4_addr_val(v)->s_addr, 4);
+    *size32Ptr = 4;
+    *size64Ptr = 4;
+    
+    CAMLreturn0;
+}
+
+static unsigned long nx_ip4_addr_deserialize(void* bufferPtr)
+{
+    deserialize_block_1(bufferPtr, 4);
+    return 4;
+}
+
+static struct custom_operations nx_ip4_addr_op = {
+    "org.conjury.ocnae.cf.in_addr",
+    custom_finalize_default,
+    nx_ip4_addr_compare,
+    nx_ip4_addr_hash,
+    nx_ip4_addr_serialize,
+    nx_ip4_addr_deserialize
+};
+
+value nx_ip4_addr_alloc(const struct in_addr* addrPtr)
+{
+    value result;
+    
+    result = alloc_custom(&nx_ip4_addr_op, 4, 0, 1);
+    *Nx_ip4_addr_val(result) = *addrPtr;
+    return result;
+}
+
+int nx_ip4_addr_category_code(const struct in_addr* addrPtr)
+{
+    u_int32_t addrN = ntohl(addrPtr->s_addr);
+    
+    if (!addrN) return Nx_ip4_addr_unspecified;
+    else if (!~addrN) return Nx_ip4_addr_broadcast;
+    else if (IN_CLASSD(addrN)) return Nx_ip4_addr_multicast;
+    else if (IN_EXPERIMENTAL(addrN)) return Nx_ip4_addr_experimental;
+    return Nx_ip4_addr_unicast;
+}
+
+/*---
+    external category: opaque t -> category = "nx_ip4_addr_category"
+  ---*/
+CAMLprim value nx_ip4_addr_category(value addr)
+{
+    CAMLparam1(addr);
+    u_int32_t n = nx_ip4_addr_category_code(Nx_ip4_addr_val(addr));
+    CAMLreturn(Val_int(n));
+}
+
+/*---
+    external is_unicast:
+        [> opaque ] t -> unicast t = "nx_ip4_addr_is_unicast"
+  ---*/
+CAMLprim value nx_ip4_addr_is_unicast(value addr)
+{
+    CAMLparam1(addr);
+    
+    u_int32_t addrN;
+    
+    addrN = Nx_ip4_addr_val(addr)->s_addr;
+    addrN = ntohl(addrN);
+    if (!(addrN && (IN_CLASSA(addrN) || IN_CLASSB(addrN) || IN_CLASSC(addrN))))
+        FAILWITH("is_unicast");
+    
+    CAMLreturn(addr);
+}
+
+/*---
+    external is_multicast:
+        [> opaque ] t -> multicast t = "nx_ip4_addr_is_multicast"
+  ---*/
+CAMLprim value nx_ip4_addr_is_multicast(value addr)
+{
+    CAMLparam1(addr);
+    
+    u_int32_t addrN;
+    
+    addrN = Nx_ip4_addr_val(addr)->s_addr;
+    addrN = ntohl(addrN);
+    if (!IN_CLASSD(addrN)) FAILWITH("is_multicast");
+    
+    CAMLreturn(addr);
+}
+
+/*---
+    external is_experimental:
+        [> opaque ] t -> experimental t = "nx_ip4_addr_is_experimental"
+  ---*/
+CAMLprim value nx_ip4_addr_is_experimental(value addr)
+{
+    CAMLparam1(addr);
+    
+    u_int32_t addrN;
+    
+    addrN = Nx_ip4_addr_val(addr)->s_addr;
+    addrN = ntohl(addrN);
+    if (!IN_EXPERIMENTAL(addrN)) FAILWITH("is_experimental");
+    
+    CAMLreturn(addr);
+}
+
+#ifndef IN_LINKLOCAL
+#define IN_LINKLOCALNETNUM    (u_int32_t)0xA9FE0000 /* 169.254.0.0 */
+#define IN_LINKLOCAL(i) \
+    (((u_int32_t)(i) & IN_CLASSB_NET) == IN_LINKLOCALNETNUM)
+#endif
+
+/*---
+    external unicast_realm:
+        [> unicast ] t -> unicast_realm = "nx_ip4_addr_unicast_realm"
+  ---*/
+CAMLprim value nx_ip4_addr_unicast_realm(value addr)
+{
+    CAMLparam1(addr);
+    
+    static const u_int32_t rfc1918_net[][2] = {
+        { 0x0A000000, 0xFF000000 },  /* 10/8        */
+        { 0xAC100000, 0xFFF00000 },  /* 172.16/12   */
+        { 0xC0A80000, 0xFFFF0000 }   /* 192.168/16  */
+    };
+        
+    u_int32_t addrN;
+    value result;
+    
+    addrN = Nx_ip4_addr_val(addr)->s_addr;
+    addrN = ntohl(addrN);
+    
+    if ((addrN & IN_CLASSA_NET) == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
+        result = Val_int(Nx_ip4_addr_U_loopback);
+    else if (IN_LINKLOCAL(addrN))
+        result = Val_int(Nx_ip4_addr_U_link);
+    else {
+        int i;
+        
+        result = Val_int(Nx_ip4_addr_U_global);
+        for (i = 0; i < 3; ++i)
+            if ((addrN & rfc1918_net[i][1]) == rfc1918_net[i][0]) {
+                result = Val_int(Nx_ip4_addr_U_private);
+                break;
+            }
+    }
+    
+    CAMLreturn(result);
+}
+
+/*---
+    external multicast_realm:
+        [> multicast ] t -> multicast_realm = "nx_ip4_addr_multicast_realm"
+  ---*/
+CAMLprim value nx_ip4_addr_multicast_realm(value addr)
+{
+    CAMLparam1(addr);
+    
+    u_int32_t addrN;
+    
+    addrN = Nx_ip4_addr_val(addr)->s_addr;
+    addrN = ntohl(addrN);
+    CAMLreturn(Val_int((addrN <= INADDR_MAX_LOCAL_GROUP)
+        ? Nx_ip4_addr_M_link : Nx_ip4_addr_M_global));
+}
+
+static value nx_ip4_addr_any_val = Val_unit;
+static value nx_ip4_addr_loopback_val = Val_unit;
+static value nx_ip4_addr_broadcast_val = Val_unit;
+static value nx_ip4_addr_empty_group_val = Val_unit;
+static value nx_ip4_addr_all_hosts_group_val = Val_unit;
+static value nx_ip4_addr_all_routers_group_val = Val_unit;
+
+/*---
+    external any_: unit -> unspecified t = "nx_ip4_addr_any"
+  ---*/
+CAMLprim value nx_ip4_addr_any(value unit)
+{
+    CAMLparam0();
+    CAMLreturn(nx_ip4_addr_any_val);
+}
+
+/*---
+    external broadcast_: unit -> broadcast t = "nx_ip4_addr_broadcast"
+  ---*/
+CAMLprim value nx_ip4_addr_loopback(value unit)
+{
+    CAMLparam0();
+    CAMLreturn(nx_ip4_addr_loopback_val);
+}
+
+/*---
+    external loopback_: unit -> unicast t = "nx_ip4_addr_loopback"
+  ---*/
+CAMLprim value nx_ip4_addr_broadcast(value unit)
+{
+    CAMLparam0();
+    CAMLreturn(nx_ip4_addr_broadcast_val);
+}
+
+/*---
+    external empty_group_: unit -> multicast t = "nx_ip4_addr_empty_group"
+  ---*/
+CAMLprim value nx_ip4_addr_empty_group(value unit)
+{
+    CAMLparam0();
+    CAMLreturn(nx_ip4_addr_empty_group_val);
+}
+
+/*---
+    external all_hosts_group_:
+        unit -> multicast t = "nx_ip4_addr_all_hosts_group"
+  ---*/
+CAMLprim value nx_ip4_addr_all_hosts_group(value unit)
+{
+    CAMLparam0();
+    CAMLreturn(nx_ip4_addr_all_hosts_group_val);
+}
+
+/*---
+    external all_routers_group_:
+        unit -> multicast t = "nx_ip4_addr_all_routers_group"
+  ---*/
+CAMLprim value nx_ip4_addr_all_routers_group(value unit)
+{
+    CAMLparam0();
+    CAMLreturn(nx_ip4_addr_all_routers_group_val);
+}
+
+/*---
+    external equal:
+        ([> opaque ] t as 'a) -> 'a -> bool = "nx_ip4_addr_equal"
+  ---*/
+CAMLprim value nx_ip4_addr_equal(value addr1, value addr2)
+{
+    CAMLparam2(addr1, addr2);
+
+    value result;
+    
+    if (Nx_ip4_addr_val(addr1)->s_addr == Nx_ip4_addr_val(addr2)->s_addr)
+        result = Val_true;
+    else
+        result = Val_false;
+    
+    CAMLreturn(result);
+}
+
+/*---
+    external compare:
+        [> opaque ] t -> [> opaque ] t -> int = "nx_ip4_addr_compare_aux"
+  ---*/
+CAMLprim value nx_ip4_addr_compare_aux(value v1, value v2)
+{
+    int d = nx_ip4_addr_compare(v1, v2);
+    return Val_int(d);
+}
+
+/*---
+    external pton: string -> opaque t = "nx_inet_pton4"
+  ---*/
+CAMLprim value nx_inet_pton4(value str)
+{
+    CAMLparam1(str);
+    CAMLlocal1(resultVal);
+
+    struct in_addr addr;
+    int result;
+    
+    result = inet_pton(AF_INET, String_val(str), &addr);
+    if (result < 0) failwith("inet_pton(AF_INET, ...)");
+    
+    resultVal = Val_int(0);
+    if (result > 0) {
+        resultVal = alloc_small(1, 0);
+        Store_field(resultVal, 0, nx_ip4_addr_alloc(&addr));
+    }
+    
+    CAMLreturn(resultVal);
+}
+
+/*---
+    external ntop: [> opaque ] t -> string = "nx_inet_ntop4"
+  ---*/
+CAMLprim value nx_inet_ntop4(value addrVal)
+{
+    CAMLparam1(addrVal);
+    CAMLlocal1(result);
+    
+    struct in_addr* addrPtr;
+    char buffer[INET_ADDRSTRLEN];
+    
+    if (!inet_ntop(AF_INET, Nx_ip4_addr_val(addrVal), buffer, sizeof buffer))
+        failwith("inet_ntop(AF_INET, ....)");
+    
+    CAMLreturn(copy_string(buffer));
+}
+
+static int nx_ip4_addr_network_min_prefix_compute
+   (const struct in_addr* addrPtr)
+{
+    u_int32_t network;
+    int prefixLen;
+    
+    network = addrPtr->s_addr;
+    network = ntohl(network);
+    
+    if (IN_CLASSA(network)) prefixLen = 8;
+    else if (IN_CLASSB(network)) prefixLen = 16;
+    else if (IN_CLASSC(network)) prefixLen = 24;
+    else prefixLen = 4;
+    
+    return prefixLen;
+}
+
+static u_int32_t nx_ip4_addr_compute_hostmask(unsigned int prefixLen)
+{
+    u_int32_t hostMask;
+    
+    hostMask = ((1 << (32 - prefixLen)) - 1);
+    return htonl(hostMask);
+}
+
+static void nx_ip4_addr_compute_limits
+   (const struct in_addr* addrPtr, unsigned int prefixLen,
+    struct in_addr* minPtr, struct in_addr* maxPtr)
+{
+    u_int32_t hostMask;
+    
+    hostMask = nx_ip4_addr_compute_hostmask(prefixLen);
+    
+    if (minPtr) minPtr->s_addr = addrPtr->s_addr & ~hostMask;
+    if (maxPtr) maxPtr->s_addr = addrPtr->s_addr | ~hostMask;
+}
+
+/*---
+    external network_min_prefix_:
+        ([> opaque ] as 'a) t -> int = "nx_ip4_addr_network_min_prefix"
+---*/
+CAMLprim value nx_ip4_addr_network_min_prefix(value addr)
+{
+    CAMLparam1(addr);
+    int result;
+    
+    result = nx_ip4_addr_network_min_prefix_compute(Nx_ip4_addr_val(addr));
+    CAMLreturn(Val_int(result));
+}
+
+/*---
+    external network_member_:
+        n:([> opaque ] as 'a) t -> p:int -> 'a t -> bool =
+        "nx_ip4_addr_network_member"
+---*/
+CAMLprim value nx_ip4_addr_network_member
+   (value networkVal, value prefixLenVal, value addrVal)
+{
+    CAMLparam3(networkVal, prefixLenVal, addrVal);
+    
+    int prefixLen, result;
+    struct in_addr* networkPtr;
+    struct in_addr* addrPtr;
+    struct in_addr min, max;
+    u_int32_t mask;
+    
+    prefixLen = Int_val(prefixLenVal);
+    if (prefixLen < 1 || prefixLen > 31) FAILWITH("network: prefix length");
+    
+    networkPtr = Nx_ip4_addr_val(networkVal);
+    addrPtr = Nx_ip4_addr_val(addrVal);
+    nx_ip4_addr_compute_limits
+       (networkPtr, (unsigned int) prefixLen, &min, &max);
+    mask = ~(min.s_addr ^ max.s_addr);
+    result = !!((networkPtr->s_addr & mask) == (addrPtr->s_addr & mask));
+
+    CAMLreturn(result ? Val_true : Val_false);
+}
+    
+/*---
+    external network_limit_:
+        n:([> opaque ] as 'a) t -> p:int -> int -> 'a t =
+        "nx_ip4_addr_network_limit"
+---*/
+CAMLprim value nx_ip4_addr_network_limit
+   (value networkVal, value prefixLenVal, value dirVal, value addrVal)
+{
+    CAMLparam4(networkVal, prefixLenVal, dirVal, addrVal);
+
+    int prefixLen, dir;
+    struct in_addr* networkPtr;
+    struct in_addr* addrPtr;
+    struct in_addr* minPtr;
+    struct in_addr* maxPtr;
+    struct in_addr limit;
+    
+    networkPtr = Nx_ip4_addr_val(networkVal);
+    prefixLen = Int_val(prefixLenVal);
+    if (prefixLen >= 4 && prefixLen < 32) {
+        u_int32_t network;
+        
+        network = networkPtr->s_addr;
+        network = ntohl(network);
+    
+        if (
+            (prefixLen < 24 && IN_CLASSC(network)) ||
+            (prefixLen < 16 && IN_CLASSB(network)) ||
+            (prefixLen < 8 && IN_CLASSA(network)) ||
+            (prefixLen < 4 /* allowed for both class D and class E */)
+        )
+            FAILWITH("network: invalid prefix length for address class");
+    }
+    else
+        FAILWITH("network: invalid prefix length");
+    
+    addrPtr = Nx_ip4_addr_val(addrVal);
+    dir = Int_val(dirVal);
+    minPtr = (dir < 0) ? &limit : 0;
+    maxPtr = (dir > 0) ? &limit : 0;
+    limit.s_addr = 0;
+    
+    nx_ip4_addr_compute_limits
+        (networkPtr, (unsigned int) prefixLen, minPtr, maxPtr);
+    
+    CAMLreturn (nx_ip4_addr_alloc(&limit));
+}
+
+/*---
+    external network_next_: 'a t -> int -> 'a t = "nx_ip4_addr_network_next"
+---*/
+CAMLprim value nx_ip4_addr_network_next(value addrVal, value stepVal)
+{
+    CAMLparam2(addrVal, stepVal);
+    
+    struct in_addr result;
+    u_int32_t x;
+    
+    x = Nx_ip4_addr_val(addrVal)->s_addr;
+    x = ntohl(x);
+    x += Val_int(stepVal);
+    result.s_addr = htonl(x);
+    CAMLreturn (nx_ip4_addr_alloc(&result));
+}
+
+/*---
+    external network_netmask_: int -> string = "nx_ip4_addr_network_netmask"
+---*/
+CAMLprim value nx_ip4_addr_network_netmask(value prefixLen)
+{
+    CAMLparam1(prefixLen);
+    
+    struct in_addr addr;
+    char buffer[INET_ADDRSTRLEN];
+    
+    addr.s_addr = ~nx_ip4_addr_compute_hostmask(Int_val(prefixLen));
+    if (inet_ntop(AF_INET, &addr, buffer, sizeof buffer) == 0)
+        failwith("inet_ntop(AF_INET, ....)");
+    
+    CAMLreturn(copy_string(buffer));
+}
+
+
+/*---
+  Initialization primitive
+  ---*/
+CAMLprim value nx_ip4_addr_init(value unit)
+{
+    struct in_addr addr;
+
+    register_custom_operations(&nx_ip4_addr_op);
+        
+    addr.s_addr = htonl(INADDR_ANY);
+    register_global_root(&nx_ip4_addr_any_val);
+    nx_ip4_addr_any_val = nx_ip4_addr_alloc(&addr);
+
+    addr.s_addr = htonl(INADDR_LOOPBACK);
+    register_global_root(&nx_ip4_addr_loopback_val);
+    nx_ip4_addr_loopback_val = nx_ip4_addr_alloc(&addr);
+
+    addr.s_addr = htonl(INADDR_BROADCAST);
+    register_global_root(&nx_ip4_addr_broadcast_val);
+    nx_ip4_addr_broadcast_val = nx_ip4_addr_alloc(&addr);
+
+    addr.s_addr = htonl(INADDR_UNSPEC_GROUP);
+    register_global_root(&nx_ip4_addr_empty_group_val);
+    nx_ip4_addr_empty_group_val = nx_ip4_addr_alloc(&addr);
+
+    addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
+    register_global_root(&nx_ip4_addr_all_hosts_group_val);
+    nx_ip4_addr_all_hosts_group_val = nx_ip4_addr_alloc(&addr);
+
+    addr.s_addr = htonl(INADDR_ALLRTRS_GROUP);
+    register_global_root(&nx_ip4_addr_all_routers_group_val);
+    nx_ip4_addr_all_routers_group_val = nx_ip4_addr_alloc(&addr);
+
+    return Val_unit;
+}
+
+/*--- End of File [ nx_ip4_addr_p.c ] ---*/

File nx/nx_ip4_addr_p.h

View file
+/*---------------------------------------------------------------------------*
+  C HEADER  nx_ip4_addr_p.h
+
+  Copyright (c) 2003-2006, James H. Woodyatt
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+    Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+  OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *---------------------------------------------------------------------------*/
+
+#ifndef _NX_IP4_ADDR_P_H
+#define _NX_IP4_ADDR_P_H
+
+#include "nx_common_p.h"
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#define Nx_ip4_addr_val(v)  ((struct in_addr*) Data_custom_val(v))
+extern value nx_ip4_addr_alloc(const struct in_addr* addrPtr);
+
+extern int nx_ip4_addr_category_code(const struct in_addr* addrPtr);
+
+enum nx_ip4_addr_category {
+    Nx_ip4_addr_unspecified,
+    Nx_ip4_addr_unicast,
+    Nx_ip4_addr_multicast,
+    Nx_ip4_addr_experimental,
+    Nx_ip4_addr_broadcast
+};
+
+#endif /* defined(_NX_IP4_ADDR_P_H) */
+
+/*--- End of File [ nx_ip4_addr_p.h ] ---*/

File nx/nx_ip4_proto.ml

View file
+(*---------------------------------------------------------------------------*
+  IMPLEMENTATION  nx_ip4_proto.ml
+
+  Copyright (c) 2003-2006, James H. Woodyatt
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+    Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+  OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *---------------------------------------------------------------------------*)
+
+external init_: unit -> unit = "nx_ip4_proto_init";;
+init_ ();;
+
+external domain_: unit -> 'a Nx_socket.domain = "nx_ip4_proto_domain"
+
+module AF = struct
+    type tag = [ `AF_INET ]
+    type address = Nx_ip4_addr.opaque Nx_ip4_addr.t * int
+    
+    let domain = domain_ ()
+
+    external to_sockaddr:
+        address -> tag Nx_socket.sockaddr = "nx_ip4_proto_to_sockaddr"
+    external of_sockaddr:
+        tag Nx_socket.sockaddr -> address = "nx_ip4_proto_of_sockaddr"
+
+    let unspecified =
+        to_sockaddr ((Nx_ip4_addr.any :> Nx_ip4_addr.opaque Nx_ip4_addr.t), 0)
+end
+
+module TCP = struct
+    module AF = AF
+    module ST = Nx_socket.SOCK_STREAM
+    let protocol = Nx_ip_common.zero
+end
+
+module UDP = struct
+    module AF = AF
+    module ST = Nx_socket.SOCK_DGRAM
+    let protocol = Nx_ip_common.zero
+end
+
+type mreq = {
+    imr_multiaddr: Nx_ip4_addr.multicast Nx_ip4_addr.t;
+    imr_interface: Nx_ip4_addr.unicast Nx_ip4_addr.t;
+}
+
+type sockopt_index =
+    IP_TTL | IP_ADD_MEMBERSHIP | IP_DROP_MEMBERSHIP | IP_MULTICAST_IF |
+    IP_MULTICAST_TTL | IP_MULTICAST_LOOP
+
+external sockopt_lift:
+    sockopt_index -> ('v,[`AF_INET],'st) Nx_socket.sockopt =
+    "nx_ip4_proto_sockopt_lift"
+
+let ip_ttl = Obj.magic (sockopt_lift IP_TTL)
+let ip_add_membership = Obj.magic (sockopt_lift IP_ADD_MEMBERSHIP)
+let ip_drop_membership = Obj.magic (sockopt_lift IP_DROP_MEMBERSHIP)
+let ip_multicast_if = Obj.magic (sockopt_lift IP_MULTICAST_IF)
+let ip_multicast_ttl = Obj.magic (sockopt_lift IP_MULTICAST_TTL)
+let ip_multicast_loop = Obj.magic (sockopt_lift IP_MULTICAST_LOOP)
+
+external siocgifaddr:
+    ([ `AF_INET ], 'st) Nx_socket.t -> string ->
+    [> Nx_ip4_addr.unicast ] Nx_ip4_addr.t = "nx_ip4_proto_siocgifaddr"
+
+(*--- End of File [ nx_ip4_proto.ml ] ---*)

File nx/nx_ip4_proto.mli

View file
+(*---------------------------------------------------------------------------*
+  INTERFACE  nx_ip4_proto.mli
+
+  Copyright (c) 2003-2006, James H. Woodyatt
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+    Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+  OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *---------------------------------------------------------------------------*)
+
+(** The [AF_INET] address family (for use with TCP and UDP over IPv4). *)
+
+(** {6 Modules and Types} *)
+
+(** The address family module for IPv4 transports. *)
+module AF: Nx_socket.AF with
+    type tag = [ `AF_INET ] and
+    type address = Nx_ip4_addr.opaque Nx_ip4_addr.t * int
+
+(** The TCP (IPv4) socket protocol. *)
+module TCP: Nx_socket.P with
+    module AF = AF and
+    module ST = Nx_socket.SOCK_STREAM
+
+(** The UDP (IPv4) socket protocol. *)
+module UDP: Nx_socket.P with
+    module AF = AF and
+    module ST = Nx_socket.SOCK_DGRAM
+
+(** The multicast request type *)
+type mreq = {
+    imr_multiaddr: Nx_ip4_addr.multicast Nx_ip4_addr.t;
+    imr_interface: Nx_ip4_addr.unicast Nx_ip4_addr.t;
+}
+
+(** {6 Socket Options}
+
+    The following socket options are available on sockets of AF_INET family.
+*)
+
+(** Set the unicast hop count for the socket. *)
+val ip_ttl: (int, [ `AF_INET ], 'st) Nx_socket.sockopt
+
+(** Add the socket to the membership of a multicast group. *)
+val ip_add_membership:
+    (mreq, [ `AF_INET ], [ `SOCK_DGRAM ]) Nx_socket.sockopt
+
+(** Drop the socket from the membership of a multicast group. *)
+val ip_drop_membership:
+    (mreq, [ `AF_INET ], [ `SOCK_DGRAM ]) Nx_socket.sockopt
+
+(** The primary network interface address for sending to multicast
+    destinations.
+*)
+val ip_multicast_if:
+    (Nx_ip4_addr.unicast Nx_ip4_addr.t, [ `AF_INET ], [ `SOCK_DGRAM ])
+    Nx_socket.sockopt
+
+(** The multicast hop count for the socket. *)
+val ip_multicast_ttl: (int, [ `AF_INET ], [ `SOCK_DGRAM ]) Nx_socket.sockopt
+
+(** Enable multicast loopback on the socket. *)
+val ip_multicast_loop:
+    (bool, [ `AF_INET ], [ `SOCK_DGRAM ]) Nx_socket.sockopt
+
+(** {6 Other Functions}
+
+    The following socket options are available on sockets of AF_INET and
+    AF_INET6 address/protocol families.
+*)
+
+(** Use [siocgifaddr sock name] with any [`AF_INET] address family socket
+    [sock] to get the primary IP address for the [name] interface.
+*)
+val siocgifaddr:
+    ([ `AF_INET ], 'st) Nx_socket.t -> string ->
+    [> Nx_ip4_addr.unicast ] Nx_ip4_addr.t
+
+(*--- End of File [ nx_ip4_proto.mli ] ---*)

File nx/nx_ip4_proto_p.c

View file
+/*---------------------------------------------------------------------------*
+  C MODULE  nx_ip4_proto_p.c
+
+  Copyright (c) 2003-2006, James H. Woodyatt
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+    Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+  OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *---------------------------------------------------------------------------*/
+
+#include "nx_ip4_proto_p.h"
+
+#include <string.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+
+#define FAILWITH(S)             (failwith("Nx_ip4_proto." S))
+#define INVALID_ARGUMENT(S)     (invalid_argument("Nx_ip4_proto." S))
+
+static int nx_ip4_proto_sockaddr_compare(value v1, value v2)
+{
+    CAMLparam2(v1, v2);
+    const struct sockaddr_in* sinAddr1Ptr;
+    const struct sockaddr_in* sinAddr2Ptr;
+    const u_int8_t* addr1Ptr;
+    const u_int8_t* addr2Ptr;
+    int i, result;
+    
+    sinAddr1Ptr = &Nx_socket_sockaddrx_val(in, v1)->sx_sockaddr_in;
+    sinAddr2Ptr = &Nx_socket_sockaddrx_val(in, v2)->sx_sockaddr_in;
+    
+    addr1Ptr = (u_int8_t*)(sinAddr1Ptr->sin_addr.s_addr) + 3;
+    addr2Ptr = (u_int8_t*)(sinAddr2Ptr->sin_addr.s_addr) + 3;
+    
+    for (i = 4; i >= 0; --i, --addr1Ptr, --addr2Ptr) {
+        result = *addr1Ptr - *addr2Ptr;
+        if (result) goto done;
+    }
+    
+    addr1Ptr = (u_int8_t*) &(sinAddr1Ptr->sin_port) + 1;
+    addr2Ptr = (u_int8_t*) &(sinAddr2Ptr->sin_port) + 1;
+    
+    for (i = 2; i >= 0; --i, --addr1Ptr, --addr2Ptr) {
+        result = *addr1Ptr - *addr2Ptr;
+        if (result) goto done;
+    }
+    
+  done:
+    CAMLreturn(result);
+}
+
+static long nx_ip4_proto_sockaddr_hash(value sxVal)
+{
+    CAMLparam1(sxVal);
+    const struct sockaddr_in* sinPtr;
+    long result;
+    
+    sinPtr = &Nx_socket_sockaddrx_val(in, sxVal)->sx_sockaddr_in;
+    result = (long) ntohl(sinPtr->sin_addr.s_addr);
+    result ^= ntohs(sinPtr->sin_port);
+    
+    CAMLreturn(result);
+}
+
+static void nx_ip4_proto_sockaddr_serialize
+   (value sxVal, unsigned long* size32Ptr, unsigned long* size64Ptr)
+{
+    CAMLparam1(sxVal);
+    const struct sockaddr_in* sinPtr;
+    
+    sinPtr = &Nx_socket_sockaddrx_val(in, sxVal)->sx_sockaddr_in;
+    serialize_int_4(ntohl(sinPtr->sin_addr.s_addr));
+    serialize_int_2(ntohs(sinPtr->sin_port));
+    
+    *size32Ptr = sizeof *sinPtr;
+    *size64Ptr = sizeof *sinPtr;
+    
+    CAMLreturn0;
+}
+
+static unsigned long nx_ip4_proto_sockaddr_deserialize(void* bufferPtr)
+{
+    struct sockaddr_in* sinPtr;
+    
+    sinPtr = (struct sockaddr_in*) bufferPtr;
+    sinPtr->sin_family = AF_INET;
+    sinPtr->sin_addr.s_addr = deserialize_uint_4();
+    sinPtr->sin_addr.s_addr = htonl(sinPtr->sin_addr.s_addr);
+    sinPtr->sin_port = deserialize_uint_2();
+    sinPtr->sin_port = htons(sinPtr->sin_port);
+    
+    return sizeof *sinPtr;
+}
+
+static struct custom_operations nx_ip4_proto_sockaddr_op = {
+    "org.conjury.ocnae.cf.sockaddr_in",
+    custom_finalize_default,
+    nx_ip4_proto_sockaddr_compare,
+    nx_ip4_proto_sockaddr_hash,
+    nx_ip4_proto_sockaddr_serialize,
+    nx_ip4_proto_sockaddr_deserialize
+};
+
+value nx_ip4_proto_sockaddr_cons(const struct sockaddr* saPtr, size_t saLen)
+{
+    value sxVal;
+    Nx_socket_sockaddrx_in_t* sxPtr;
+    const size_t sxLen =
+        offsetof(Nx_socket_sockaddrx_in_t, sx_sockaddr_in) +
+        sizeof(struct sockaddr_in);
+            
+    sxVal = alloc_custom(&nx_ip4_proto_sockaddr_op, sxLen, 0, 1);
+    sxPtr = Nx_socket_sockaddrx_val(in, sxVal);
+    if (sxPtr) {
+        sxPtr->sx_socklen = saLen;
+        memcpy(&sxPtr->sx_sockaddr_in, saPtr, saLen);
+    }
+    
+    return sxVal;
+}
+
+static value nx_ip4_proto_domain_val = Val_unit;
+
+/*---
+    external domain_: unit -> 'a Nx_socket.domain_t = "nx_ip4_proto_domain"
+  ---*/
+CAMLprim value nx_ip4_proto_domain(value unit)
+{
+    CAMLparam0();
+    CAMLreturn(nx_ip4_proto_domain_val);
+}
+
+/*---
+    external to_sockaddr:
+        Nx_ip4_addr.opaque Nx_ip4_addr.t * int ->
+        [`AF_INET] Nx_socket.sockaddr_t = "nx_ip4_proto_to_sockaddr"
+  ---*/
+CAMLprim value nx_ip4_proto_to_sockaddr(value addrVal)
+{
+    CAMLparam1(addrVal);
+    CAMLlocal1(resultVal);
+    
+    struct sockaddr_in sin;
+    int port;
+    
+    port = Int_val(Field(addrVal, 1));
+    if (port < 0 || port > 65535)
+        INVALID_ARGUMENT("to_sockaddr: invalid port number");
+    
+    memset(&sin, 0, sizeof sin);
+    sin.sin_family = AF_INET;
+    sin.sin_port = htons(port);
+    sin.sin_addr = *Nx_ip4_addr_val(Field(addrVal, 0));
+    
+    resultVal =
+        nx_ip4_proto_sockaddr_cons((struct sockaddr*) &sin, sizeof sin);
+    CAMLreturn(resultVal);
+}
+
+/*---
+    external of_sockaddr:
+        [`AF_INET] Nx_socket.sockaddr_t ->
+        Nx_ip4_addr.opaque Nx_ip4_addr.t * int = "nx_ip4_proto_of_sockaddr"
+  ---*/
+CAMLprim value nx_ip4_proto_of_sockaddr(value sxVal)
+{
+    CAMLparam1(sxVal);
+    CAMLlocal2(addrVal, resultVal);
+    
+    const Nx_socket_sockaddrx_in_t* sxPtr;
+    const struct sockaddr_in* sinPtr;
+    
+    sxPtr = Nx_socket_sockaddrx_val(in, sxVal);
+    sinPtr = &sxPtr->sx_sockaddr_in;
+    addrVal = nx_ip4_addr_alloc(&sinPtr->sin_addr);
+    
+    resultVal = alloc_small(2, 0);
+    Field(resultVal, 0) = addrVal;
+    Field(resultVal, 1) = Val_int(ntohs(sinPtr->sin_port));
+
+    CAMLreturn(resultVal);
+}
+
+/*---
+    external siocgifaddr:
+        ([ `AF_INET ], 'st) Nx_socket.t -> string ->
+        [> Nx_ip4_addr.unicast ] Nx_ip4_addr.t = "nx_ip4_proto_siocgifaddr"
+  ---*/
+CAMLprim value nx_ip4_proto_siocgifaddr(value sockVal, value nameVal)
+{
+    CAMLparam2(sockVal, nameVal);
+    CAMLlocal1(resultVal);
+    const char* namePtr;
+    const Nx_socket_t* sockPtr;
+    char buffer[IF_NAMESIZE + sizeof(struct sockaddr_storage)];
+    struct ifreq* ifrPtr;
+    const struct sockaddr_in* sinPtr;
+    int v;
+    
+    namePtr = String_val(nameVal);
+    if (string_length(nameVal) > IF_NAMESIZE || strlen(namePtr) >= IF_NAMESIZE)
+        invalid_argument("ioctl[SIOCGIFADDR]: name too long.");
+    
+    memset(buffer, 0, sizeof buffer);
+    ifrPtr = (struct ifreq*) buffer;
+    strcpy(ifrPtr->ifr_name, String_val(nameVal));
+    sockPtr = Nx_socket_val(sockVal);
+
+    v = ioctl(sockPtr->s_fd, SIOCGIFADDR, buffer);
+    if (v == -1) unix_error(errno, "ioctl[SIOCGIFADDR]", Nothing);
+
+    sinPtr = (const struct sockaddr_in*) &ifrPtr->ifr_addr;
+    resultVal = nx_ip4_addr_alloc(&sinPtr->sin_addr);
+    CAMLreturn(resultVal);
+}
+
+value nx_ip4_proto_getsockopt_uchar
+   (const Nx_socket_option_context_t* contextPtr)
+{
+    u_char optval;
+    socklen_t optlen;
+    
+    memset(&optval, 0, sizeof optval);
+    optlen = sizeof optval;
+    nx_socket_getsockopt_guard(contextPtr, &optval, &optlen);
+        
+    return Val_int(optval);
+}
+
+void nx_ip4_proto_setsockopt_uchar
+   (const Nx_socket_option_context_t* contextPtr, value x)
+{
+    u_char optval;
+    int n;
+    
+    n = Int_val(x);
+    if (n < 0 || n > 0xFF)
+        invalid_argument("Nx_ip4_proto.setsockopt[uchar]: range error.");
+    
+    optval = n;
+    nx_socket_setsockopt_guard(contextPtr, &optval, sizeof optval);
+}
+
+value nx_ip4_proto_getsockopt_addr