diff --git a/LibraryDoc b/LibraryDoc
index 619a7729388fb4541c0b4d7dc78f64d5b3320807..4c9ed94d0b0f27c1adb6e674d9a7ec7c07aebffc 100644
--- a/LibraryDoc
+++ b/LibraryDoc
@@ -1,4 +1,4 @@
-Acorn TCP/IP libraries version 5.26
+Acorn TCP/IP libraries version 5.30
 -----------------------------------
 
 These libraries are an update to the libraries described in chapter 123 of the PRM
@@ -1261,6 +1261,39 @@ New prototypes: u_long inet_addr(const char *cp);
                 u_long inet_network(const char *cp);
 		struct in_addr inet_makeaddr(u_long net, u_long host);
 
+Four new functions have been defined:
+
+	char *inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size);
+	
+This function convert network number from network to presentation format.
+Generates CIDR style result always.  The return value is pointer to dst, or
+NULL if an error occurred (check errno).
+
+	int inet_net_pton(int af, const char *buf, void *, size_t);
+	
+This function parses a presentation format (ie. textual) address into a
+network address (the reverse operation to inet_net_ntop).   af is the address
+type (AF_INET or AF_INET6); buf points to the textual representation, buf
+points to the output buffer and size is the length of that buffer.  The
+return value is the number of bits, either imputed classfully or specified
+with /CIDR, or -1 if some failure occurred (check errno). ENOENT means it was
+not a valid network specification.
+
+	int inet_pton(int af, const char *src, void *dst);
+	
+Convert from presentation format (which usually means ASCII printable) to network
+format (which is usually some kind of binary format).  Return:
+  1 if the address was valid for the specified address family
+  0 if the address wasn't valid (`dst' is untouched in this case)
+ -1 if some other error occurred (`dst' is untouched in this case, too)
+
+	const char *inet_ntop(int af, const void *src, char *dst, size_t size);
+
+Convert a network format address to presentation format.  Returns a pointer to
+presentation format address (`dst'), or NULL (see errno).
+
+
+
 _INET_ERROR
 ===========
 
diff --git a/VersionNum b/VersionNum
index eee2c700bb9fd64060903105fc2cd67a00bbd37e..1123d65b74bdab59ef4ad6e0ef21c9c5708da952 100644
--- a/VersionNum
+++ b/VersionNum
@@ -1,15 +1,15 @@
-/* (5.29)
+/* (5.30)
  *
  * This file is automatically maintained by srccommit, do not edit manually.
  *
  */
-#define Module_MajorVersion_CMHG     	5.29
+#define Module_MajorVersion_CMHG     	5.30
 #define Module_MinorVersion_CMHG	
-#define Module_Date_CMHG      		22 Jul 1999
+#define Module_Date_CMHG      		28 Jul 1999
 
-#define Module_MajorVersion     	"5.29"
-#define Module_Version                  529
+#define Module_MajorVersion     	"5.30"
+#define Module_Version                  530
 #define Module_MinorVersion		""
-#define Module_Date      		"22 Jul 1999"
+#define Module_Date      		"28 Jul 1999"
 
-#define Module_FullVersion              "5.29"
+#define Module_FullVersion              "5.30"
diff --git a/headers/arpa/h/inet b/headers/arpa/h/inet
index bf6fba9e96f127c6217d2f2971adee1cbdfb01e9..a8d1fea4526bb700e81427d4ef1a0b2292f39e67 100644
--- a/headers/arpa/h/inet
+++ b/headers/arpa/h/inet
@@ -47,7 +47,11 @@ unsigned long	 inet_lnaof(struct in_addr);
 struct in_addr	 inet_makeaddr(u_long , u_long);
 unsigned long	 inet_netof(struct in_addr);
 unsigned long	 inet_network(const char *);
+char		*inet_net_ntop(int, const void *, int, char *, size_t);
+int		 inet_net_pton(int, const char *, void *, size_t);
 char		*inet_ntoa(struct in_addr);
+int		 inet_pton(int, const char *, void *);
+const char	*inet_ntop(int, const void *, char *, size_t);
 __END_DECLS
 
 #endif /* !_INET_H_ */
diff --git a/headers/arpa/h/nameser b/headers/arpa/h/nameser
index bf0ab59b1a7d390a0a13255d751a7045c9d408af..9fc685ea98985d956aad284ab65820c92acb733f 100644
--- a/headers/arpa/h/nameser
+++ b/headers/arpa/h/nameser
@@ -87,6 +87,7 @@
 #define	INT32SZ		4		/* for systems without 32-bit ints */
 #define	INT16SZ		2		/* for systems without 16-bit ints */
 #define	INADDRSZ	4		/* for sizeof(struct inaddr) != 4 */
+#define IN6ADDRSZ	16		/* IPv6 T_AAAA */
 
 /*
  * Internet nameserver port number
@@ -158,12 +159,19 @@
 #define	T_GPOS		27		/* geographical position (withdrawn) */
 #define	T_AAAA		28		/* IP6 Address */
 #define	T_LOC		29		/* Location Information */
+#define T_NXT		30		/* Next Valid Name in Zone */
+#define T_EID		31		/* Endpoint identifier */
+#define T_NIMLOC	32		/* Nimrod locator */
+#define T_SRV		33		/* Server selection */
+#define T_ATMA		34		/* ATM Address */
+#define T_NAPTR		35		/* Naming Authority PoinTeR */
 	/* non standard */
 #define	T_UINFO		100		/* user (finger) information */
 #define	T_UID		101		/* user ID */
 #define	T_GID		102		/* group ID */
 #define	T_UNSPEC	103		/* Unspecified format (binary data) */
 	/* Query type values which do not appear in resource records */
+#define	T_IXFR		251		/* incremental zone transfer */
 #define	T_AXFR		252		/* transfer zone of authority */
 #define	T_MAILB		253		/* transfer mailbox records */
 #define	T_MAILA		254		/* transfer mail agent records */
@@ -179,6 +187,48 @@
 	/* Query class values which do not appear in resource records */
 #define	C_ANY		255		/* wildcard match */
 
+/*
+ * Flags field of the KEY RR rdata
+ */
+#define	KEYFLAG_TYPEMASK	0xC000	/* Mask for "type" bits */
+#define	KEYFLAG_TYPE_AUTH_CONF	0x0000	/* Key usable for both */
+#define	KEYFLAG_TYPE_CONF_ONLY	0x8000	/* Key usable for confidentiality */
+#define	KEYFLAG_TYPE_AUTH_ONLY	0x4000	/* Key usable for authentication */
+#define	KEYFLAG_TYPE_NO_KEY	0xC000	/* No key usable for either; no key */
+/* The type bits can also be interpreted independently, as single bits: */
+#define	KEYFLAG_NO_AUTH		0x8000	/* Key not usable for authentication */
+#define	KEYFLAG_NO_CONF		0x4000	/* Key not usable for confidentiality */
+
+#define	KEYFLAG_EXPERIMENTAL	0x2000	/* Security is *mandatory* if bit=0 */
+#define	KEYFLAG_RESERVED3	0x1000  /* reserved - must be zero */
+#define	KEYFLAG_RESERVED4	0x0800  /* reserved - must be zero */
+#define	KEYFLAG_USERACCOUNT	0x0400	/* key is assoc. with a user acct */
+#define	KEYFLAG_ENTITY		0x0200	/* key is assoc. with entity eg host */
+#define	KEYFLAG_ZONEKEY		0x0100	/* key is zone key for the zone named */
+#define	KEYFLAG_IPSEC		0x0080  /* key is for IPSEC use (host or user)*/
+#define	KEYFLAG_EMAIL		0x0040  /* key is for email (MIME security) */
+#define	KEYFLAG_RESERVED10	0x0020  /* reserved - must be zero */
+#define	KEYFLAG_RESERVED11	0x0010  /* reserved - must be zero */
+#define	KEYFLAG_SIGNATORYMASK	0x000F	/* key can sign DNS RR's of same name */
+
+#define  KEYFLAG_RESERVED_BITMASK ( KEYFLAG_RESERVED3 | \
+				    KEYFLAG_RESERVED4 | \
+				    KEYFLAG_RESERVED10| KEYFLAG_RESERVED11)
+
+/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */
+#define	ALGORITHM_MD5RSA	1	/* MD5 with RSA */
+#define	ALGORITHM_EXPIRE_ONLY	253	/* No alg, no security */
+#define	ALGORITHM_PRIVATE_OID	254	/* Key begins with OID indicating alg */
+
+/* Signatures */
+					/* Size of a mod or exp in bits */
+#define	MIN_MD5RSA_KEY_PART_BITS	 512
+#define	MAX_MD5RSA_KEY_PART_BITS	2552
+					/* Total of binary mod and exp, bytes */
+#define	MAX_MD5RSA_KEY_BYTES		((MAX_MD5RSA_KEY_PART_BITS+7/8)*2+3)
+					/* Max length of text sig block */
+#define	MAX_KEY_BASE64			(((MAX_MD5RSA_KEY_BYTES+2)/3)*4)
+
 /*
  * Status return codes for T_UNSPEC conversion routines
  */
diff --git a/headers/sys/h/socket b/headers/sys/h/socket
index a309ae8701c1763c7e00c4aeafbbb5cb0edb1eea..d61bec43886809342b6b5db007f7ed7eddb80b10 100644
--- a/headers/sys/h/socket
+++ b/headers/sys/h/socket
@@ -122,8 +122,12 @@ struct  linger {
 #define	pseudo_AF_PIP	25		/* Help Identify PIP packets */
 #define	AF_ISDN		26		/* Integrated Services Digital Network*/
 #define	AF_E164		AF_ISDN		/* CCITT E.164 recommendation */
+#define pseudo_AF_KEY   27              /* Internal key-management function */
+#define AF_INET6        28              /* IPv6 */
+#define AF_NATM         29              /* native ATM access */
+#define AF_ATM          30              /* ATM */
 
-#define AF_MAX          27
+#define AF_MAX          31
 
 /*
  * Structure used by kernel to store most
@@ -184,6 +188,10 @@ struct sockproto {
 #define PF_RTIP		pseudo_AF_FTIP	/* same format as AF_INET */
 #define PF_PIP		pseudo_AF_PIP
 #define	PF_ISDN		AF_ISDN
+#define	PF_KEY		pseudo_AF_KEY
+#define	PF_INET6	AF_INET6
+#define	PF_NATM		AF_NATM
+#define	PF_ATM		AF_ATM
 
 #define PF_MAX          AF_MAX
 
@@ -224,6 +232,10 @@ struct sockproto {
 	{ "ipx", CTLTYPE_NODE }, \
 	{ "sip", CTLTYPE_NODE }, \
 	{ "pip", CTLTYPE_NODE }, \
+	{ "isdn", CTLTYPE_NODE }, \
+	{ "key", CTLTYPE_NODE }, \
+	{ "inet6", CTLTYPE_NODE }, \
+	{ "natm", CTLTYPE_NODE }, \
 }
 
 /*
diff --git a/inetlib/Makefile b/inetlib/Makefile
index e96a998508ca8c2769312394ec1ddae35d4de9da..4aacba28c538db42d03e84e15c1c0487da0b756f 100644
--- a/inetlib/Makefile
+++ b/inetlib/Makefile
@@ -57,19 +57,22 @@ CFILES=		gethent.c gethnad.c getnbyad.c getnbyna.c getnent.c \
 		getprent.c getprnam.c getproto.c getsbyna.c getsbypo.c \
 		getsent.c htonl.c inet_addr.c inet_lnaof.c inet_maddr.c \
 		inet_nof.c inet_ntoa.c inet_nwork.c rresvport.c \
-		linkaddr.c ns_addr.c ns_ntoa.c iso_addr.c sysctlbyna.c
+		linkaddr.c ns_addr.c ns_ntoa.c iso_addr.c sysctlbyna.c \
+		inet_nntop.c inet_npton.c inet_ntop.c inet_pton.c
 
 OFILES=		gethent.o gethnad.o getnbyad.o getnbyna.o getnent.o \
 		getprent.o getprnam.o getproto.o getsbyna.o getsbypo.o \
 		getsent.o htonl.o inet_addr.o inet_lnaof.o inet_maddr.o \
 		inet_nof.o inet_ntoa.o inet_nwork.o rresvport.o \
-		linkaddr.o ns_addr.o ns_ntoa.o iso_addr.o sysctlbyna.o
+		linkaddr.o ns_addr.o ns_ntoa.o iso_addr.o sysctlbyna.o \
+		inet_nntop.o inet_npton.o inet_ntop.o inet_pton.o
 
 ZFILES=		z.gethent z.gethnad z.getnbyad z.getnbyna z.getnent \
 		z.getprent z.getprnam z.getproto z.getsbyna z.getsbypo \
 		z.getsent z.htonl z.inet_addr z.inet_lnaof z.inet_maddr \
 		z.inet_nof z.inet_ntoa z.inet_nwork z.rresvport \
-		z.linkaddr z.ns_addr z.ns_ntoa z.iso_addr z.sysctlbyna
+		z.linkaddr z.ns_addr z.ns_ntoa z.iso_addr z.sysctlbyna \
+		z.inet_nntop z.inet_npton z.inet_ntop z.inet_pton
 
 .SUFFIXES:	.z .o .c .s
 
diff --git a/inetlib/c/inet_nntop b/inetlib/c/inet_nntop
new file mode 100644
index 0000000000000000000000000000000000000000..a65841522f5da6329c9a48482d78188e4e5ddcbc
--- /dev/null
+++ b/inetlib/c/inet_nntop
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id$";
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <sys/errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "inetlib.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static char *	inet_net_ntop_ipv4(const u_char *src, int bits,
+					char *dst, size_t size);
+
+/*
+ * char *
+ * inet_net_ntop(af, src, bits, dst, size)
+ *	convert network number from network to presentation format.
+ *	generates CIDR style result always.
+ * return:
+ *	pointer to dst, or NULL if an error occurred (check errno).
+ * author:
+ *	Paul Vixie (ISC), July 1996
+ */
+char *
+inet_net_ntop(af, src, bits, dst, size)
+	int af;
+	const void *src;
+	int bits;
+	char *dst;
+	size_t size;
+{
+	switch (af) {
+	case AF_INET:
+		return (inet_net_ntop_ipv4(src, bits, dst, size));
+	default:
+		errno = EAFNOSUPPORT;
+		return (NULL);
+	}
+}
+
+/*
+ * static char *
+ * inet_net_ntop_ipv4(src, bits, dst, size)
+ *	convert IPv4 network number from network to presentation format.
+ *	generates CIDR style result always.
+ * return:
+ *	pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ *	network byte order assumed.  this means 192.5.5.240/28 has
+ *	0x11110000 in its fourth octet.
+ * author:
+ *	Paul Vixie (ISC), July 1996
+ */
+static char *
+inet_net_ntop_ipv4(src, bits, dst, size)
+	const u_char *src;
+	int bits;
+	char *dst;
+	size_t size;
+{
+	char *odst = dst;
+	char *t;
+	u_int m;
+	int b;
+
+	if (bits < 0 || bits > 32) {
+		errno = EINVAL;
+		return (NULL);
+	}
+	if (bits == 0) {
+		if (size < sizeof "0")
+			goto emsgsize;
+		*dst++ = '0';
+		*dst = '\0';
+	}
+
+	/* Format whole octets. */
+	for (b = bits / 8; b > 0; b--) {
+		if (size < sizeof "255.")
+			goto emsgsize;
+		t = dst;
+		dst += SPRINTF((dst, "%u", *src++));
+		if (b > 1) {
+			*dst++ = '.';
+			*dst = '\0';
+		}
+		size -= (size_t)(dst - t);
+	}
+
+	/* Format partial octet. */
+	b = bits % 8;
+	if (b > 0) {
+		if (size < sizeof ".255")
+			goto emsgsize;
+		t = dst;
+		if (dst != odst)
+			*dst++ = '.';
+		m = ((1 << b) - 1) << (8 - b);
+		dst += SPRINTF((dst, "%u", *src & m));
+		size -= (size_t)(dst - t);
+	}
+
+	/* Format CIDR /width. */
+	if (size < sizeof "/32")
+		goto emsgsize;
+	dst += SPRINTF((dst, "/%u", bits));
+	return (odst);
+
+ emsgsize:
+	errno = EMSGSIZE;
+	return (NULL);
+}
diff --git a/inetlib/c/inet_npton b/inetlib/c/inet_npton
new file mode 100644
index 0000000000000000000000000000000000000000..e752efe9eb3968f7170e9dd102bf611b2fa31195
--- /dev/null
+++ b/inetlib/c/inet_npton
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id$";
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#define NDEBUG
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "inetlib.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+#define isascii(val) (1)
+
+static int	inet_net_pton_ipv4(const char *src, u_char *dst,
+					size_t size);
+
+/*
+ * static int
+ * inet_net_pton(af, src, dst, size)
+ *	convert network number from presentation to network format.
+ *	accepts hex octets, hex strings, decimal octets, and /CIDR.
+ *	"size" is in bytes and describes "dst".
+ * return:
+ *	number of bits, either imputed classfully or specified with /CIDR,
+ *	or -1 if some failure occurred (check errno).  ENOENT means it was
+ *	not a valid network specification.
+ * author:
+ *	Paul Vixie (ISC), June 1996
+ */
+int
+inet_net_pton(af, src, dst, size)
+	int af;
+	const char *src;
+	void *dst;
+	size_t size;
+{
+	switch (af) {
+	case AF_INET:
+		return (inet_net_pton_ipv4(src, dst, size));
+	default:
+		errno = EAFNOSUPPORT;
+		return (-1);
+	}
+}
+
+/*
+ * static int
+ * inet_net_pton_ipv4(src, dst, size)
+ *	convert IPv4 network number from presentation to network format.
+ *	accepts hex octets, hex strings, decimal octets, and /CIDR.
+ *	"size" is in bytes and describes "dst".
+ * return:
+ *	number of bits, either imputed classfully or specified with /CIDR,
+ *	or -1 if some failure occurred (check errno).  ENOENT means it was
+ *	not an IPv4 network specification.
+ * note:
+ *	network byte order assumed.  this means 192.5.5.240/28 has
+ *	0x11110000 in its fourth octet.
+ * author:
+ *	Paul Vixie (ISC), June 1996
+ */
+static int
+inet_net_pton_ipv4(src, dst, size)
+	const char *src;
+	u_char *dst;
+	size_t size;
+{
+	static const char
+		xdigits[] = "0123456789abcdef",
+		digits[] = "0123456789";
+	int n, ch, tmp, dirty, bits;
+	const u_char *odst = dst;
+
+	ch = *src++;
+	if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
+	    && isascii(src[1]) && isxdigit(src[1])) {
+		/* Hexadecimal: Eat nybble string. */
+		if (size <= 0)
+			goto emsgsize;
+		*dst = 0, dirty = 0;
+		src++;	/* skip x or X. */
+		while ((ch = *src++) != '\0' &&
+		       isascii(ch) && isxdigit(ch)) {
+			if (isupper(ch))
+				ch = tolower(ch);
+			n = strchr(xdigits, ch) - xdigits;
+			assert(n >= 0 && n <= 15);
+			*dst |= n;
+			if (!dirty++)
+				*dst <<= 4;
+			else if (size-- > 0)
+				*++dst = 0, dirty = 0;
+			else
+				goto emsgsize;
+		}
+		if (dirty)
+			size--;
+	} else if (isascii(ch) && isdigit(ch)) {
+		/* Decimal: eat dotted digit string. */
+		for (;;) {
+			tmp = 0;
+			do {
+				n = strchr(digits, ch) - digits;
+				assert(n >= 0 && n <= 9);
+				tmp *= 10;
+				tmp += n;
+				if (tmp > 255)
+					goto enoent;
+			} while ((ch = *src++) != '\0' &&
+				 isascii(ch) && isdigit(ch));
+			if (size-- <= 0)
+				goto emsgsize;
+			*dst++ = (u_char) tmp;
+			if (ch == '\0' || ch == '/')
+				break;
+			if (ch != '.')
+				goto enoent;
+			ch = *src++;
+			if (!isascii(ch) || !isdigit(ch))
+				goto enoent;
+		}
+	} else
+		goto enoent;
+
+	bits = -1;
+	if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) {
+		/* CIDR width specifier.  Nothing can follow it. */
+		ch = *src++;	/* Skip over the /. */
+		bits = 0;
+		do {
+			n = strchr(digits, ch) - digits;
+			assert(n >= 0 && n <= 9);
+			bits *= 10;
+			bits += n;
+		} while ((ch = *src++) != '\0' &&
+			 isascii(ch) && isdigit(ch));
+		if (ch != '\0')
+			goto enoent;
+		if (bits > 32)
+			goto emsgsize;
+	}
+
+	/* Firey death and destruction unless we prefetched EOS. */
+	if (ch != '\0')
+		goto enoent;
+
+	/* If nothing was written to the destination, we found no address. */
+	if (dst == odst)
+		goto enoent;
+	/* If no CIDR spec was given, infer width from net class. */
+	if (bits == -1) {
+		if (*odst >= 240)	/* Class E */
+			bits = 32;
+		else if (*odst >= 224)	/* Class D */
+			bits = 4;
+		else if (*odst >= 192)	/* Class C */
+			bits = 24;
+		else if (*odst >= 128)	/* Class B */
+			bits = 16;
+		else			/* Class A */
+			bits = 8;
+		/* If imputed mask is narrower than specified octets, widen. */
+		if (bits >= 8 && bits < ((dst - odst) * 8))
+			bits = (dst - odst) * 8;
+	}
+	/* Extend network to cover the actual mask. */
+	while (bits > ((dst - odst) * 8)) {
+		if (size-- <= 0)
+			goto emsgsize;
+		*dst++ = '\0';
+	}
+	return (bits);
+
+ enoent:
+	errno = ENOENT;
+	return (-1);
+
+ emsgsize:
+	errno = EMSGSIZE;
+	return (-1);
+}
diff --git a/inetlib/c/inet_ntop b/inetlib/c/inet_ntop
new file mode 100644
index 0000000000000000000000000000000000000000..5f655fe0ad1e41bfbac486aa12f3dfc847052dd2
--- /dev/null
+++ b/inetlib/c/inet_ntop
@@ -0,0 +1,197 @@
+/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/errno.h>
+#include <stdio.h>
+
+#include "inetlib.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static const char *inet_ntop4(const u_char *src, char *dst, size_t size);
+static const char *inet_ntop6(const u_char *src, char *dst, size_t size);
+
+/* char *
+ * inet_ntop(af, src, dst, size)
+ *	convert a network format address to presentation format.
+ * return:
+ *	pointer to presentation format address (`dst'), or NULL (see errno).
+ * author:
+ *	Paul Vixie, 1996.
+ */
+const char *
+inet_ntop(af, src, dst, size)
+	int af;
+	const void *src;
+	char *dst;
+	size_t size;
+{
+	switch (af) {
+	case AF_INET:
+		return (inet_ntop4(src, dst, size));
+	case AF_INET6:
+		return (inet_ntop6(src, dst, size));
+	default:
+		errno = EAFNOSUPPORT;
+		return (NULL);
+	}
+	/* NOTREACHED */
+}
+
+/* const char *
+ * inet_ntop4(src, dst, size)
+ *	format an IPv4 address, more or less like inet_ntoa()
+ * return:
+ *	`dst' (as a const)
+ * notes:
+ *	(1) uses no statics
+ *	(2) takes a u_char* not an in_addr as input
+ * author:
+ *	Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop4(src, dst, size)
+	const u_char *src;
+	char *dst;
+	size_t size;
+{
+	static const char fmt[] = "%u.%u.%u.%u";
+	char tmp[sizeof "255.255.255.255"];
+
+	if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) > size) {
+		errno = ENOSPC;
+		return (NULL);
+	}
+	strcpy(dst, tmp);
+	return (dst);
+}
+
+/* const char *
+ * inet_ntop6(src, dst, size)
+ *	convert IPv6 binary address into presentation (printable) format
+ * author:
+ *	Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop6(src, dst, size)
+	const u_char *src;
+	char *dst;
+	size_t size;
+{
+	/*
+	 * Note that int32_t and int16_t need only be "at least" large enough
+	 * to contain a value of the specified size.  On some systems, like
+	 * Crays, there is no such thing as an integer variable with 16 bits.
+	 * Keep this in mind if you think this function should have been coded
+	 * to use pointer overlays.  All the world's not a VAX.
+	 */
+	char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
+	struct { int base, len; } best, cur;
+	u_int words[IN6ADDRSZ / INT16SZ];
+	int i;
+
+	/*
+	 * Preprocess:
+	 *	Copy the input (bytewise) array into a wordwise array.
+	 *	Find the longest run of 0x00's in src[] for :: shorthanding.
+	 */
+	memset(words, '\0', sizeof words);
+	for (i = 0; i < IN6ADDRSZ; i++)
+		words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+	best.base = -1;
+	cur.base = -1;
+	for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
+		if (words[i] == 0) {
+			if (cur.base == -1)
+				cur.base = i, cur.len = 1;
+			else
+				cur.len++;
+		} else {
+			if (cur.base != -1) {
+				if (best.base == -1 || cur.len > best.len)
+					best = cur;
+				cur.base = -1;
+			}
+		}
+	}
+	if (cur.base != -1) {
+		if (best.base == -1 || cur.len > best.len)
+			best = cur;
+	}
+	if (best.base != -1 && best.len < 2)
+		best.base = -1;
+
+	/*
+	 * Format the result.
+	 */
+	tp = tmp;
+	for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
+		/* Are we inside the best run of 0x00's? */
+		if (best.base != -1 && i >= best.base &&
+		    i < (best.base + best.len)) {
+			if (i == best.base)
+				*tp++ = ':';
+			continue;
+		}
+		/* Are we following an initial run of 0x00s or any real hex? */
+		if (i != 0)
+			*tp++ = ':';
+		/* Is this address an encapsulated IPv4? */
+		if (i == 6 && best.base == 0 &&
+		    (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
+			if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
+				return (NULL);
+			tp += strlen(tp);
+			break;
+		}
+		tp += SPRINTF((tp, "%x", words[i]));
+	}
+	/* Was it a trailing run of 0x00's? */
+	if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
+		*tp++ = ':';
+	*tp++ = '\0';
+
+	/*
+	 * Check for overflow, copy, and we're done.
+	 */
+	if ((size_t)(tp - tmp) > size) {
+		errno = ENOSPC;
+		return (NULL);
+	}
+	strcpy(dst, tmp);
+	return (dst);
+}
diff --git a/inetlib/c/inet_pton b/inetlib/c/inet_pton
new file mode 100644
index 0000000000000000000000000000000000000000..f62f59e8498b04e55c5aee2339a1e9be937301ef
--- /dev/null
+++ b/inetlib/c/inet_pton
@@ -0,0 +1,217 @@
+/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/errno.h>
+
+#include "inetlib.h"
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static int	inet_pton4(const char *src, u_char *dst);
+static int	inet_pton6(const char *src, u_char *dst);
+
+/* int
+ * inet_pton(af, src, dst)
+ *	convert from presentation format (which usually means ASCII printable)
+ *	to network format (which is usually some kind of binary format).
+ * return:
+ *	1 if the address was valid for the specified address family
+ *	0 if the address wasn't valid (`dst' is untouched in this case)
+ *	-1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ *	Paul Vixie, 1996.
+ */
+int
+inet_pton(af, src, dst)
+	int af;
+	const char *src;
+	void *dst;
+{
+	switch (af) {
+	case AF_INET:
+		return (inet_pton4(src, dst));
+	case AF_INET6:
+		return (inet_pton6(src, dst));
+	default:
+		errno = EAFNOSUPPORT;
+		return (-1);
+	}
+	/* NOTREACHED */
+}
+
+/* int
+ * inet_pton4(src, dst)
+ *	like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ *	1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ *	does not touch `dst' unless it's returning 1.
+ * author:
+ *	Paul Vixie, 1996.
+ */
+static int
+inet_pton4(src, dst)
+	const char *src;
+	u_char *dst;
+{
+	static const char digits[] = "0123456789";
+	int saw_digit, octets, ch;
+	u_char tmp[INADDRSZ], *tp;
+
+	saw_digit = 0;
+	octets = 0;
+	*(tp = tmp) = 0;
+	while ((ch = *src++) != '\0') {
+		const char *pch;
+
+		if ((pch = strchr(digits, ch)) != NULL) {
+			u_int new = *tp * 10 + (pch - digits);
+
+			if (new > 255)
+				return (0);
+			*tp = new;
+			if (! saw_digit) {
+				if (++octets > 4)
+					return (0);
+				saw_digit = 1;
+			}
+		} else if (ch == '.' && saw_digit) {
+			if (octets == 4)
+				return (0);
+			*++tp = 0;
+			saw_digit = 0;
+		} else
+			return (0);
+	}
+	if (octets < 4)
+		return (0);
+
+	memcpy(dst, tmp, INADDRSZ);
+	return (1);
+}
+
+/* int
+ * inet_pton6(src, dst)
+ *	convert presentation level address to network order binary form.
+ * return:
+ *	1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ *	(1) does not touch `dst' unless it's returning 1.
+ *	(2) :: in a full address is silently ignored.
+ * credit:
+ *	inspired by Mark Andrews.
+ * author:
+ *	Paul Vixie, 1996.
+ */
+static int
+inet_pton6(src, dst)
+	const char *src;
+	u_char *dst;
+{
+	static const char xdigits_l[] = "0123456789abcdef",
+			  xdigits_u[] = "0123456789ABCDEF";
+	u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
+	const char *xdigits, *curtok;
+	int ch, saw_xdigit;
+	u_int val;
+
+	memset((tp = tmp), '\0', IN6ADDRSZ);
+	endp = tp + IN6ADDRSZ;
+	colonp = NULL;
+	/* Leading :: requires some special handling. */
+	if (*src == ':')
+		if (*++src != ':')
+			return (0);
+	curtok = src;
+	saw_xdigit = 0;
+	val = 0;
+	while ((ch = *src++) != '\0') {
+		const char *pch;
+
+		if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+			pch = strchr((xdigits = xdigits_u), ch);
+		if (pch != NULL) {
+			val <<= 4;
+			val |= (pch - xdigits);
+			if (val > 0xffff)
+				return (0);
+			saw_xdigit = 1;
+			continue;
+		}
+		if (ch == ':') {
+			curtok = src;
+			if (!saw_xdigit) {
+				if (colonp)
+					return (0);
+				colonp = tp;
+				continue;
+			}
+			if (tp + INT16SZ > endp)
+				return (0);
+			*tp++ = (u_char) (val >> 8) & 0xff;
+			*tp++ = (u_char) val & 0xff;
+			saw_xdigit = 0;
+			val = 0;
+			continue;
+		}
+		if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
+		    inet_pton4(curtok, tp) > 0) {
+			tp += INADDRSZ;
+			saw_xdigit = 0;
+			break;	/* '\0' was seen by inet_pton4(). */
+		}
+		return (0);
+	}
+	if (saw_xdigit) {
+		if (tp + INT16SZ > endp)
+			return (0);
+		*tp++ = (u_char) (val >> 8) & 0xff;
+		*tp++ = (u_char) val & 0xff;
+	}
+	if (colonp != NULL) {
+		/*
+		 * Since some memmove()'s erroneously fail to handle
+		 * overlapping regions, we'll do the shift by hand.
+		 */
+		const int n = tp - colonp;
+		int i;
+
+		for (i = 1; i <= n; i++) {
+			endp[- i] = colonp[n - i];
+			colonp[n - i] = 0;
+		}
+		tp = endp;
+	}
+	if (tp != endp)
+		return (0);
+	memcpy(dst, tmp, IN6ADDRSZ);
+	return (1);
+}
diff --git a/inetlib/h/inetlib b/inetlib/h/inetlib
index bb516c5f5652ac1fcbfba57d5cf25246dc5b867d..3a8db6f9ba8403d43292791a95ae5a2c0fbdb963 100644
--- a/inetlib/h/inetlib
+++ b/inetlib/h/inetlib
@@ -75,7 +75,11 @@ extern u_long inet_lnaof(struct in_addr in);
 extern struct in_addr inet_makeaddr(u_long net, u_long host);
 extern u_long inet_network(const char *cp);
 extern u_long inet_netof(struct in_addr in);
-extern char *inet_ntoa(struct in_addr in);
+extern char *inet_net_ntop(int, const void *, int, char *, size_t);
+extern int inet_net_pton(int, const char *, void *, size_t);
+extern char *inet_ntoa(struct in_addr);
+extern const char *inet_ntop(int, const void *, char *, size_t);
+extern int inet_pton(int, const char *, void *);
 
 extern struct hostent *namisipadr(const char *nam);
 extern u_long ntohl(u_long x);