diff options
| author | Peter Wemm <peter@FreeBSD.org> | 1998-06-11 09:03:02 +0000 | 
|---|---|---|
| committer | Peter Wemm <peter@FreeBSD.org> | 1998-06-11 09:03:02 +0000 | 
| commit | 14b93edab315672d87e6fe82aaff8e7ee7378e0b (patch) | |
| tree | b521683c722481012df1712a7d17ca84afecfae7 /lib/libc | |
| parent | a28ce30ec5add9bffb06bd8e1c5cfdf45637e682 (diff) | |
Notes
Diffstat (limited to 'lib/libc')
| -rw-r--r-- | lib/libc/net/Makefile.inc | 9 | ||||
| -rw-r--r-- | lib/libc/net/base64.c | 37 | ||||
| -rw-r--r-- | lib/libc/net/herror.c | 29 | ||||
| -rw-r--r-- | lib/libc/net/inet_net_pton.c | 7 | ||||
| -rw-r--r-- | lib/libc/net/inet_network.c | 5 | ||||
| -rw-r--r-- | lib/libc/net/inet_ntoa.c | 20 | ||||
| -rw-r--r-- | lib/libc/net/inet_ntop.c | 15 | ||||
| -rw-r--r-- | lib/libc/net/inet_pton.c | 22 | ||||
| -rw-r--r-- | lib/libc/net/ns_name.c | 593 | ||||
| -rw-r--r-- | lib/libc/net/ns_netint.c | 54 | ||||
| -rw-r--r-- | lib/libc/net/ns_parse.c | 190 | ||||
| -rw-r--r-- | lib/libc/net/ns_print.c | 743 | ||||
| -rw-r--r-- | lib/libc/net/ns_ttl.c | 151 | ||||
| -rw-r--r-- | lib/libc/net/nsap_addr.c | 12 | ||||
| -rw-r--r-- | lib/libc/net/res_comp.c | 748 | ||||
| -rw-r--r-- | lib/libc/net/res_config.h | 2 | ||||
| -rw-r--r-- | lib/libc/net/res_data.c | 94 | ||||
| -rw-r--r-- | lib/libc/net/res_debug.c | 1010 | ||||
| -rw-r--r-- | lib/libc/net/res_init.c | 45 | ||||
| -rw-r--r-- | lib/libc/net/res_mkquery.c | 39 | ||||
| -rw-r--r-- | lib/libc/net/res_mkupdate.c | 414 | ||||
| -rw-r--r-- | lib/libc/net/res_query.c | 61 | ||||
| -rw-r--r-- | lib/libc/net/res_send.c | 115 | ||||
| -rw-r--r-- | lib/libc/net/res_stubs.c | 21 | ||||
| -rw-r--r-- | lib/libc/net/res_update.c | 516 | 
25 files changed, 3219 insertions, 1733 deletions
diff --git a/lib/libc/net/Makefile.inc b/lib/libc/net/Makefile.inc index d01fd2ecc660..18dca25178f0 100644 --- a/lib/libc/net/Makefile.inc +++ b/lib/libc/net/Makefile.inc @@ -1,5 +1,5 @@  #	from @(#)Makefile.inc	8.2 (Berkeley) 9/5/93 -#	$Id: Makefile.inc,v 1.25 1997/10/21 08:41:08 bde Exp $ +#	$Id: Makefile.inc,v 1.26 1998/02/20 08:15:55 jb Exp $  # machine-independent net sources  .PATH: ${.CURDIR}/../libc/${MACHINE_ARCH}/net ${.CURDIR}/../libc/net @@ -11,10 +11,11 @@ SRCS+=	addr2ascii.c ascii2addr.c base64.c ether_addr.c \  	getservbyport.c getservent.c herror.c inet_addr.c inet_lnaof.c \  	inet_makeaddr.c inet_net_ntop.c inet_net_pton.c inet_neta.c \  	inet_netof.c inet_network.c inet_ntoa.c inet_ntop.c \ -	inet_pton.c linkaddr.c map_v4v6.c ns_addr.c ns_ntoa.c nsap_addr.c \ +	inet_pton.c linkaddr.c map_v4v6.c ns_addr.c ns_name.c ns_netint.c \ +	ns_ntoa.c ns_parse.c ns_print.c ns_ttl.c nsap_addr.c \  	rcmd.c recv.c res_comp.c res_data.c res_debug.c \ -	res_init.c res_mkquery.c res_query.c res_send.c res_stubs.c \ -	send.c +	res_init.c res_mkquery.c res_mkupdate.c res_query.c res_send.c \ +	res_stubs.c res_update.c send.c  # not supported: iso_addr.c   # machine-dependent net sources diff --git a/lib/libc/net/base64.c b/lib/libc/net/base64.c index 868826a777dc..3f2ed6c71420 100644 --- a/lib/libc/net/base64.c +++ b/lib/libc/net/base64.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 1996 by Internet Software Consortium. + * Copyright (c) 1996, 1998 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 @@ -40,9 +40,14 @@   * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.   */ +#if !defined(LINT) && !defined(CODECENTER) +static char rcsid[] = "$Id: base64.c,v 8.5 1998/03/27 00:17:46 halley Exp $"; +#endif /* not lint */ +  #include <sys/types.h>  #include <sys/param.h>  #include <sys/socket.h> +  #include <netinet/in.h>  #include <arpa/inet.h>  #include <arpa/nameser.h> @@ -50,13 +55,8 @@  #include <ctype.h>  #include <resolv.h>  #include <stdio.h> - -#if defined(BSD) && (BSD >= 199103) && defined(AF_INET6) -# include <stdlib.h> -# include <string.h> -#else -# include "../conf/portability.h" -#endif +#include <stdlib.h> +#include <string.h>  #define Assert(Cond) if (!(Cond)) abort() @@ -128,16 +128,11 @@ static const char Pad64 = '=';     */  int -b64_ntop(src, srclength, target, targsize) -	u_char const *src; -	size_t srclength; -	char *target; -	size_t targsize; -{ +b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) {  	size_t datalength = 0;  	u_char input[3];  	u_char output[4]; -	int i; +	size_t i;  	while (2 < srclength) {  		input[0] = *src++; @@ -224,7 +219,7 @@ b64_pton(src, target, targsize)  		switch (state) {  		case 0:  			if (target) { -				if (tarindex >= targsize) +				if ((size_t)tarindex >= targsize)  					return (-1);  				target[tarindex] = (pos - Base64) << 2;  			} @@ -232,7 +227,7 @@ b64_pton(src, target, targsize)  			break;  		case 1:  			if (target) { -				if (tarindex + 1 >= targsize) +				if ((size_t)tarindex + 1 >= targsize)  					return (-1);  				target[tarindex]   |=  (pos - Base64) >> 4;  				target[tarindex+1]  = ((pos - Base64) & 0x0f) @@ -243,7 +238,7 @@ b64_pton(src, target, targsize)  			break;  		case 2:  			if (target) { -				if (tarindex + 1 >= targsize) +				if ((size_t)tarindex + 1 >= targsize)  					return (-1);  				target[tarindex]   |=  (pos - Base64) >> 2;  				target[tarindex+1]  = ((pos - Base64) & 0x03) @@ -254,7 +249,7 @@ b64_pton(src, target, targsize)  			break;  		case 3:  			if (target) { -				if (tarindex >= targsize) +				if ((size_t)tarindex >= targsize)  					return (-1);  				target[tarindex] |= (pos - Base64);  			} @@ -280,7 +275,7 @@ b64_pton(src, target, targsize)  		case 2:		/* Valid, means one byte of info */  			/* Skip any number of spaces. */ -			for (NULL; ch != '\0'; ch = *src++) +			for ((void)NULL; ch != '\0'; ch = *src++)  				if (!isspace(ch))  					break;  			/* Make sure there is another trailing = sign. */ @@ -295,7 +290,7 @@ b64_pton(src, target, targsize)  			 * We know this char is an =.  Is there anything but  			 * whitespace after it?  			 */ -			for (NULL; ch != '\0'; ch = *src++) +			for ((void)NULL; ch != '\0'; ch = *src++)  				if (!isspace(ch))  					return (-1); diff --git a/lib/libc/net/herror.c b/lib/libc/net/herror.c index f22f519fa7e0..ac3ca3bd9cb2 100644 --- a/lib/libc/net/herror.c +++ b/lib/libc/net/herror.c @@ -1,4 +1,4 @@ -/*- +/*   * Copyright (c) 1987, 1993   *	The Regents of the University of California.  All rights reserved.   * @@ -29,38 +29,35 @@   * 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. - * - - * Portions Copyright (c) 1993 by Digital Equipment Corporation. + */ + +/* + * Portions 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, and that - * the name of Digital Equipment Corporation not be used in advertising or - * publicity pertaining to distribution of the document or software without - * specific, written prior permission. + * copyright notice and this permission notice appear in all copies.   * - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT - * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * 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. - * - - * --Copyright--   */  #if defined(LIBC_SCCS) && !defined(lint)  static char sccsid[] = "@(#)herror.c	8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id$"; +static char rcsid[] = "$Id: herror.c,v 1.6 1997/02/22 15:00:14 peter Exp $";  #endif /* LIBC_SCCS and not lint */  #include <sys/types.h>  #include <sys/uio.h>  #include <netdb.h> -#include <unistd.h>  #include <string.h> +#include <unistd.h>  const char *h_errlist[] = {  	"Resolver Error 0 (no error)", @@ -71,7 +68,7 @@ const char *h_errlist[] = {  };  int	h_nerr = { sizeof h_errlist / sizeof h_errlist[0] }; -extern int	h_errno; +int	h_errno;  /*   * herror -- diff --git a/lib/libc/net/inet_net_pton.c b/lib/libc/net/inet_net_pton.c index 6fd6a06c6da9..6718329b8472 100644 --- a/lib/libc/net/inet_net_pton.c +++ b/lib/libc/net/inet_net_pton.c @@ -16,8 +16,8 @@   */  #if defined(LIBC_SCCS) && !defined(lint) -static const char orig_rcsid[] = "From Id: inet_net_pton.c,v 8.3 1996/11/11 06:36:52 vixie Exp"; -static const char rcsid[] = "$Id$"; +static const char orig_rcsid[] = "From Id: inet_net_pton.c,v 1.8 1996/11/21 10:28:12 vixie Exp $"; +static const char rcsid[] = "$Id: inet_net_pton.c,v 1.3 1997/02/22 15:00:18 peter Exp $";  #endif  #include <sys/types.h> @@ -159,8 +159,7 @@ inet_net_pton_ipv4(src, dst, size)  			assert(n >= 0 && n <= 9);  			bits *= 10;  			bits += n; -		} while ((ch = *src++) != '\0' && -			 isascii(ch) && isdigit(ch)); +		} while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));  		if (ch != '\0')  			goto enoent;  		if (bits > 32) diff --git a/lib/libc/net/inet_network.c b/lib/libc/net/inet_network.c index 6da2e8bc4d61..a62efc7185ca 100644 --- a/lib/libc/net/inet_network.c +++ b/lib/libc/net/inet_network.c @@ -49,10 +49,9 @@ u_long  inet_network(cp)  	register const char *cp;  { -	register u_long val, base, n; +	register u_long val, base, n, i;  	register char c;  	u_long parts[4], *pp = parts; -	register int i;  again:  	val = 0; base = 10; @@ -60,7 +59,7 @@ again:  		base = 8, cp++;  	if (*cp == 'x' || *cp == 'X')  		base = 16, cp++; -	while ( (c = *cp) ) { +	while ((c = *cp) != 0) {  		if (isdigit(c)) {  			val = (val * base) + (c - '0');  			cp++; diff --git a/lib/libc/net/inet_ntoa.c b/lib/libc/net/inet_ntoa.c index a37b1dbeefd1..4fdceeed4873 100644 --- a/lib/libc/net/inet_ntoa.c +++ b/lib/libc/net/inet_ntoa.c @@ -35,25 +35,23 @@  static char sccsid[] = "@(#)inet_ntoa.c	8.1 (Berkeley) 6/4/93";  #endif /* LIBC_SCCS and not lint */ -/* - * Convert network-format internet address - * to base 256 d.d.d.d representation. - */  #include <sys/types.h> +#include <sys/socket.h>  #include <netinet/in.h>  #include <arpa/inet.h>  #include <stdio.h> +/* + * Convert network-format internet address + * to base 256 d.d.d.d representation. + */  char *  inet_ntoa(in)  	struct in_addr in;  { -	static char b[18]; -	register char *p; +	static char ret[18]; -	p = (char *)∈ -#define	UC(b)	(((int)b)&0xff) -	(void)snprintf(b, sizeof(b), -	    "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3])); -	return (b); +	strcpy(ret, "[inet_ntoa error]"); +	(void) inet_ntop(AF_INET, &in, ret, sizeof ret); +	return (ret);  } diff --git a/lib/libc/net/inet_ntop.c b/lib/libc/net/inet_ntop.c index 36dcb3264dff..c44a973467f8 100644 --- a/lib/libc/net/inet_ntop.c +++ b/lib/libc/net/inet_ntop.c @@ -15,7 +15,7 @@   */  #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$Id$"; +static char rcsid[] = "$Id: inet_ntop.c,v 1.3 1997/02/22 15:00:21 peter Exp $";  #endif /* LIBC_SCCS and not lint */  #include <sys/param.h> @@ -24,9 +24,9 @@ static char rcsid[] = "$Id$";  #include <netinet/in.h>  #include <arpa/inet.h>  #include <arpa/nameser.h> -#include <string.h>  #include <errno.h>  #include <stdio.h> +#include <string.h>  #define SPRINTF(x) ((size_t)sprintf x) @@ -114,7 +114,7 @@ inet_ntop6(src, dst, size)  	 */  	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]; +	u_int words[NS_IN6ADDRSZ / NS_INT16SZ];  	int i;  	/* @@ -123,11 +123,11 @@ inet_ntop6(src, dst, size)  	 *	Find the longest run of 0x00's in src[] for :: shorthanding.  	 */  	memset(words, '\0', sizeof words); -	for (i = 0; i < IN6ADDRSZ; i++) +	for (i = 0; i < NS_IN6ADDRSZ; i++)  		words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));  	best.base = -1;  	cur.base = -1; -	for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { +	for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {  		if (words[i] == 0) {  			if (cur.base == -1)  				cur.base = i, cur.len = 1; @@ -152,7 +152,7 @@ inet_ntop6(src, dst, size)  	 * Format the result.  	 */  	tp = tmp; -	for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { +	for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {  		/* Are we inside the best run of 0x00's? */  		if (best.base != -1 && i >= best.base &&  		    i < (best.base + best.len)) { @@ -174,7 +174,8 @@ inet_ntop6(src, dst, size)  		tp += SPRINTF((tp, "%x", words[i]));  	}  	/* Was it a trailing run of 0x00's? */ -	if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) +	if (best.base != -1 && (best.base + best.len) == +	    (NS_IN6ADDRSZ / NS_INT16SZ))  		*tp++ = ':';  	*tp++ = '\0'; diff --git a/lib/libc/net/inet_pton.c b/lib/libc/net/inet_pton.c index 054ff7dbb2c7..19f28fb578c4 100644 --- a/lib/libc/net/inet_pton.c +++ b/lib/libc/net/inet_pton.c @@ -15,7 +15,7 @@   */  #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$Id$"; +static char rcsid[] = "$Id: inet_pton.c,v 1.3 1997/02/22 15:00:22 peter Exp $";  #endif /* LIBC_SCCS and not lint */  #include <sys/param.h> @@ -81,7 +81,7 @@ inet_pton4(src, dst)  {  	static const char digits[] = "0123456789";  	int saw_digit, octets, ch; -	u_char tmp[INADDRSZ], *tp; +	u_char tmp[NS_INADDRSZ], *tp;  	saw_digit = 0;  	octets = 0; @@ -111,7 +111,7 @@ inet_pton4(src, dst)  	if (octets < 4)  		return (0); -	memcpy(dst, tmp, INADDRSZ); +	memcpy(dst, tmp, NS_INADDRSZ);  	return (1);  } @@ -135,13 +135,13 @@ inet_pton6(src, dst)  {  	static const char xdigits_l[] = "0123456789abcdef",  			  xdigits_u[] = "0123456789ABCDEF"; -	u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp; +	u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;  	const char *xdigits, *curtok;  	int ch, saw_xdigit;  	u_int val; -	memset((tp = tmp), '\0', IN6ADDRSZ); -	endp = tp + IN6ADDRSZ; +	memset((tp = tmp), '\0', NS_IN6ADDRSZ); +	endp = tp + NS_IN6ADDRSZ;  	colonp = NULL;  	/* Leading :: requires some special handling. */  	if (*src == ':') @@ -171,7 +171,7 @@ inet_pton6(src, dst)  				colonp = tp;  				continue;  			} -			if (tp + INT16SZ > endp) +			if (tp + NS_INT16SZ > endp)  				return (0);  			*tp++ = (u_char) (val >> 8) & 0xff;  			*tp++ = (u_char) val & 0xff; @@ -179,16 +179,16 @@ inet_pton6(src, dst)  			val = 0;  			continue;  		} -		if (ch == '.' && ((tp + INADDRSZ) <= endp) && +		if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&  		    inet_pton4(curtok, tp) > 0) { -			tp += INADDRSZ; +			tp += NS_INADDRSZ;  			saw_xdigit = 0;  			break;	/* '\0' was seen by inet_pton4(). */  		}  		return (0);  	}  	if (saw_xdigit) { -		if (tp + INT16SZ > endp) +		if (tp + NS_INT16SZ > endp)  			return (0);  		*tp++ = (u_char) (val >> 8) & 0xff;  		*tp++ = (u_char) val & 0xff; @@ -209,6 +209,6 @@ inet_pton6(src, dst)  	}  	if (tp != endp)  		return (0); -	memcpy(dst, tmp, IN6ADDRSZ); +	memcpy(dst, tmp, NS_IN6ADDRSZ);  	return (1);  } diff --git a/lib/libc/net/ns_name.c b/lib/libc/net/ns_name.c new file mode 100644 index 000000000000..bd4de80950df --- /dev/null +++ b/lib/libc/net/ns_name.c @@ -0,0 +1,593 @@ +/* + * 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. + */ + +#ifndef lint +static char rcsid[] = "$Id: ns_name.c,v 8.3 1997/04/24 22:10:54 vixie Exp $"; +#endif + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv.h> +#include <string.h> + +/* Data. */ + +static char		digits[] = "0123456789"; + +/* Forward. */ + +static int		special(int); +static int		printable(int); +static int		dn_find(const u_char *, const u_char *, +				const u_char * const *, +				const u_char * const *); + +/* Public. */ + +/* + * ns_name_ntop(src, dst, dstsiz) + *	Convert an encoded domain name to printable ascii as per RFC1035. + * return: + *	Number of bytes written to buffer, or -1 (with errno set) + * notes: + *	The root is returned as "." + *	All other domains are returned in non absolute form + */ +int +ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) { +	const u_char *cp; +	char *dn, *eom; +	u_char c; +	u_int n; + +	cp = src; +	dn = dst; +	eom = dst + dstsiz; + +	while ((n = *cp++) != 0) { +		if ((n & NS_CMPRSFLGS) != 0) { +			/* Some kind of compression pointer. */ +			errno = EMSGSIZE; +			return (-1); +		} +		if (dn != dst) { +			if (dn >= eom) { +				errno = EMSGSIZE; +				return (-1); +			} +			*dn++ = '.'; +		} +		if (dn + n >= eom) { +			errno = EMSGSIZE; +			return (-1); +		} +		for ((void)NULL; n > 0; n--) { +			c = *cp++; +			if (special(c)) { +				if (dn + 1 >= eom) { +					errno = EMSGSIZE; +					return (-1); +				} +				*dn++ = '\\'; +				*dn++ = (char)c; +			} else if (!printable(c)) { +				if (dn + 3 >= eom) { +					errno = EMSGSIZE; +					return (-1); +				} +				*dn++ = '\\'; +				*dn++ = digits[c / 100]; +				*dn++ = digits[(c % 100) / 10]; +				*dn++ = digits[c % 10]; +			} else { +				if (dn >= eom) { +					errno = EMSGSIZE; +					return (-1); +				} +				*dn++ = (char)c; +			} +		} +	} +	if (dn == dst) { +		if (dn >= eom) { +			errno = EMSGSIZE; +			return (-1); +		} +		*dn++ = '.'; +	} +	if (dn >= eom) { +		errno = EMSGSIZE; +		return (-1); +	} +	*dn++ = '\0'; +	return (dn - dst); +} + +/* + * ns_name_pton(src, dst, dstsiz) + *	Convert a ascii string into an encoded domain name as per RFC1035. + * return: + *	-1 if it fails + *	1 if string was fully qualified + *	0 is string was not fully qualified + * notes: + *	Enforces label and domain length limits. + */ + +int +ns_name_pton(const char *src, u_char *dst, size_t dstsiz) { +	u_char *label, *bp, *eom; +	int c, n, escaped; +	char *cp; + +	escaped = 0; +	bp = dst; +	eom = dst + dstsiz; +	label = bp++; + +	while ((c = *src++) != 0) { +		if (escaped) { +			if ((cp = strchr(digits, c)) != NULL) { +				n = (cp - digits) * 100; +				if ((c = *src++) == 0 || +				    (cp = strchr(digits, c)) == NULL) { +					errno = EMSGSIZE; +					return (-1); +				} +				n += (cp - digits) * 10; +				if ((c = *src++) == 0 || +				    (cp = strchr(digits, c)) == NULL) { +					errno = EMSGSIZE; +					return (-1); +				} +				n += (cp - digits); +				if (n > 255) { +					errno = EMSGSIZE; +					return (-1); +				} +				c = n; +			} +			escaped = 0; +		} else if (c == '\\') { +			escaped = 1; +			continue; +		} else if (c == '.') { +			c = (bp - label - 1); +			if ((c & NS_CMPRSFLGS) != 0) {	/* Label too big. */ +				errno = EMSGSIZE; +				return (-1); +			} +			if (label >= eom) { +				errno = EMSGSIZE; +				return (-1); +			} +			*label = c; +			/* Fully qualified ? */ +			if (*src == '\0') { +				if (c != 0) { +					if (bp >= eom) { +						errno = EMSGSIZE; +						return (-1); +					} +					*bp++ = '\0'; +				} +				if ((bp - dst) > MAXCDNAME) { +					errno = EMSGSIZE; +					return (-1); +				} +				return (1); +			} +			if (c == 0) { +				errno = EMSGSIZE; +				return (-1); +			} +			label = bp++; +			continue; +		} +		if (bp >= eom) { +			errno = EMSGSIZE; +			return (-1); +		} +		*bp++ = (u_char)c; +	} +	c = (bp - label - 1); +	if ((c & NS_CMPRSFLGS) != 0) {		/* Label too big. */ +		errno = EMSGSIZE; +		return (-1); +	} +	if (label >= eom) { +		errno = EMSGSIZE; +		return (-1); +	} +	*label = c; +	if (c != 0) { +		if (bp >= eom) { +			errno = EMSGSIZE; +			return (-1); +		} +		*bp++ = 0; +	} +	if ((bp - dst) > MAXCDNAME) {	/* src too big */ +		errno = EMSGSIZE; +		return (-1); +	} +	return (0); +} + +/* + * ns_name_unpack(msg, eom, src, dst, dstsiz) + *	Unpack a domain name from a message, source may be compressed. + * return: + *	-1 if it fails, or consumed octets if it succeeds. + */ +int +ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, +	       u_char *dst, size_t dstsiz) +{ +	const u_char *srcp, *dstlim; +	u_char *dstp; +	int n, c, len, checked; + +	len = -1; +	checked = 0; +	dstp = dst; +	srcp = src; +	dstlim = dst + dstsiz; +	if (srcp < msg || srcp >= eom) { +		errno = EMSGSIZE; +		return (-1); +	} +	/* Fetch next label in domain name. */ +	while ((n = *srcp++) != 0) { +		/* Check for indirection. */ +		switch (n & NS_CMPRSFLGS) { +		case 0: +			/* Limit checks. */ +			if (dstp + n + 1 >= dstlim || srcp + n >= eom) { +				errno = EMSGSIZE; +				return (-1); +			} +			checked += n + 1; +			*dstp++ = n; +			memcpy(dstp, srcp, n); +			dstp += n; +			srcp += n; +			break; + +		case NS_CMPRSFLGS: +			if (srcp >= eom) { +				errno = EMSGSIZE; +				return (-1); +			} +			if (len < 0) +				len = srcp - src + 1; +			srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); +			if (srcp < msg || srcp >= eom) {  /* Out of range. */ +				errno = EMSGSIZE; +				return (-1); +			} +			checked += 2; +			/* +			 * Check for loops in the compressed name; +			 * if we've looked at the whole message, +			 * there must be a loop. +			 */ +			if (checked >= eom - msg) { +				errno = EMSGSIZE; +				return (-1); +			} +			break; + +		default: +			errno = EMSGSIZE; +			return (-1);			/* flag error */ +		} +	} +	*dstp = '\0'; +	if (len < 0) +		len = srcp - src; +	return (len); +} + +/* + * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr) + *	Pack domain name 'domain' into 'comp_dn'. + * return: + *	Size of the compressed name, or -1. + * notes: + *	'dnptrs' is an array of pointers to previous compressed names. + *	dnptrs[0] is a pointer to the beginning of the message. The array + *	ends with NULL. + *	'lastdnptr' is a pointer to the end of the array pointed to + *	by 'dnptrs'. + * Side effects: + *	The list of pointers in dnptrs is updated for labels inserted into + *	the message as we compress the name.  If 'dnptr' is NULL, we don't + *	try to compress names. If 'lastdnptr' is NULL, we don't update the + *	list. + */ +int +ns_name_pack(const u_char *src, u_char *dst, int dstsiz, +	     const u_char **dnptrs, const u_char **lastdnptr) +{ +	u_char *dstp; +	const u_char **cpp, **lpp, *eob, *msg; +	const u_char *srcp; +	int n, l; + +	srcp = src; +	dstp = dst; +	eob = dstp + dstsiz; +	lpp = cpp = NULL; +	if (dnptrs != NULL) { +		if ((msg = *dnptrs++) != NULL) { +			for (cpp = dnptrs; *cpp != NULL; cpp++) +				(void)NULL; +			lpp = cpp;	/* end of list to search */ +		} +	} else +		msg = NULL; + +	/* make sure the domain we are about to add is legal */ +	l = 0; +	do { +		n = *srcp; +		if ((n & NS_CMPRSFLGS) != 0) { +			errno = EMSGSIZE; +			return (-1); +		} +		l += n + 1; +		if (l > MAXCDNAME) { +			errno = EMSGSIZE; +			return (-1); +		} +		srcp += n + 1; +	} while (n != 0); + +	srcp = src; +	do { +		/* Look to see if we can use pointers. */ +		n = *srcp; +		if (n != 0 && msg != NULL) { +			l = dn_find(srcp, msg, (const u_char * const *)dnptrs, +				    (const u_char * const *)lpp); +			if (l >= 0) { +				if (dstp + 1 >= eob) { +					errno = EMSGSIZE; +					return (-1); +				} +				*dstp++ = (l >> 8) | NS_CMPRSFLGS; +				*dstp++ = l % 256; +				return (dstp - dst); +			} +			/* Not found, save it. */ +			if (lastdnptr != NULL && cpp < lastdnptr - 1 && +			    (dstp - msg) < 0x4000) { +				*cpp++ = dstp; +				*cpp = NULL; +			} +		} +		/* copy label to buffer */ +		if (n & NS_CMPRSFLGS) {		/* Should not happen. */ +			errno = EMSGSIZE; +			return (-1); +		} +		if (dstp + 1 + n >= eob) { +			errno = EMSGSIZE; +			return (-1); +		} +		memcpy(dstp, srcp, n + 1); +		srcp += n + 1; +		dstp += n + 1; +	} while (n != 0); + +	if (dstp > eob) { +		if (msg != NULL) +			*lpp = NULL; +		errno = EMSGSIZE; +		return (-1); +	}  +	return (dstp - dst); +} + +/* + * ns_name_uncompress(msg, eom, src, dst, dstsiz) + *	Expand compressed domain name to presentation format. + * return: + *	Number of bytes read out of `src', or -1 (with errno set). + * note: + *	Root domain returns as "." not "". + */ +int +ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src, +		   char *dst, size_t dstsiz) +{ +	u_char tmp[NS_MAXCDNAME]; +	int n; +	 +	if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1) +		return (-1); +	if (ns_name_ntop(tmp, dst, dstsiz) == -1) +		return (-1); +	return (n); +} + +/* + * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr) + *	Compress a domain name into wire format, using compression pointers. + * return: + *	Number of bytes consumed in `dst' or -1 (with errno set). + * notes: + *	'dnptrs' is an array of pointers to previous compressed names. + *	dnptrs[0] is a pointer to the beginning of the message. + *	The list ends with NULL.  'lastdnptr' is a pointer to the end of the + *	array pointed to by 'dnptrs'. Side effect is to update the list of + *	pointers for labels inserted into the message as we compress the name. + *	If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' + *	is NULL, we don't update the list. + */ +int +ns_name_compress(const char *src, u_char *dst, size_t dstsiz, +		 const u_char **dnptrs, const u_char **lastdnptr) +{ +	u_char tmp[NS_MAXCDNAME]; + +	if (ns_name_pton(src, tmp, sizeof tmp) == -1) +		return (-1); +	return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr)); +} + +/* + * ns_name_skip(ptrptr, eom) + *	Advance *ptrptr to skip over the compressed name it points at. + * return: + *	0 on success, -1 (with errno set) on failure. + */ +int +ns_name_skip(const u_char **ptrptr, const u_char *eom) { +	const u_char *cp; +	u_int n; + +	cp = *ptrptr; +	while (cp < eom && (n = *cp++) != 0) { +		/* Check for indirection. */ +		switch (n & NS_CMPRSFLGS) { +		case 0:			/* normal case, n == len */ +			cp += n; +			continue; +		case NS_CMPRSFLGS:	/* indirection */ +			cp++; +			break; +		default:		/* illegal type */ +			errno = EMSGSIZE; +			return (-1); +		} +		break; +	} +	if (cp > eom) { +		errno = EMSGSIZE; +		return (-1); +	} +	*ptrptr = cp; +	return (0); +} + +/* Private. */ + +/* + * special(ch) + *	Thinking in noninternationalized USASCII (per the DNS spec), + *	is this characted special ("in need of quoting") ? + * return: + *	boolean. + */ +static int +special(int ch) { +	switch (ch) { +	case 0x22: /* '"' */ +	case 0x2E: /* '.' */ +	case 0x3B: /* ';' */ +	case 0x5C: /* '\\' */ +	/* Special modifiers in zone files. */ +	case 0x40: /* '@' */ +	case 0x24: /* '$' */ +		return (1); +	default: +		return (0); +	} +} + +/* + * printable(ch) + *	Thinking in noninternationalized USASCII (per the DNS spec), + *	is this character visible and not a space when printed ? + * return: + *	boolean. + */ +static int +printable(int ch) { +	return (ch > 0x20 && ch < 0x7f); +} + +/* + *	Thinking in noninternationalized USASCII (per the DNS spec), + *	convert this character to lower case if it's upper case. + */ +static int +mklower(int ch) { +	if (ch >= 0x41 && ch <= 0x5A) +		return (ch + 0x20); +	return (ch); +} + +/* + * dn_find(domain, msg, dnptrs, lastdnptr) + *	Search for the counted-label name in an array of compressed names. + * return: + *	offset from msg if found, or -1. + * notes: + *	dnptrs is the pointer to the first name on the list, + *	not the pointer to the start of the message. + */ +static int +dn_find(const u_char *domain, const u_char *msg, +	const u_char * const *dnptrs, +	const u_char * const *lastdnptr) +{ +	const u_char *dn, *cp, *sp; +	const u_char * const *cpp; +	u_int n; + +	for (cpp = dnptrs; cpp < lastdnptr; cpp++) { +		dn = domain; +		sp = cp = *cpp; +		while ((n = *cp++) != 0) { +			/* +			 * check for indirection +			 */ +			switch (n & NS_CMPRSFLGS) { +			case 0:			/* normal case, n == len */ +				if (n != *dn++) +					goto next; +				for ((void)NULL; n > 0; n--) +					if (mklower(*dn++) != mklower(*cp++)) +						goto next; +				/* Is next root for both ? */ +				if (*dn == '\0' && *cp == '\0') +					return (sp - msg); +				if (*dn) +					continue; +				goto next; + +			case NS_CMPRSFLGS:	/* indirection */ +				cp = msg + (((n & 0x3f) << 8) | *cp); +				break; + +			default:	/* illegal type */ +				errno = EMSGSIZE; +				return (-1); +			} +		} + next: ; +	} +	errno = ENOENT; +	return (-1); +} diff --git a/lib/libc/net/ns_netint.c b/lib/libc/net/ns_netint.c new file mode 100644 index 000000000000..0dc8fe4699d1 --- /dev/null +++ b/lib/libc/net/ns_netint.c @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#ifndef lint +static char rcsid[] = "$Id: ns_netint.c,v 8.1 1996/11/18 09:09:57 vixie Exp $"; +#endif + +/* Import. */ + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +u_int +ns_get16(const u_char *src) { +	u_int dst; + +	NS_GET16(dst, src); +	return (dst); +} + +u_long +ns_get32(const u_char *src) { +	u_long dst; + +	NS_GET32(dst, src); +	return (dst); +} + +void +ns_put16(u_int src, u_char *dst) { +	NS_PUT16(src, dst); +} + +void +ns_put32(u_long src, u_char *dst) { +	NS_PUT32(src, dst); +} diff --git a/lib/libc/net/ns_parse.c b/lib/libc/net/ns_parse.c new file mode 100644 index 000000000000..318b36340eae --- /dev/null +++ b/lib/libc/net/ns_parse.c @@ -0,0 +1,190 @@ +/* + * 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. + */ + +#ifndef lint +static char rcsid[] = "$Id: ns_parse.c,v 8.8 1998/02/17 17:20:33 vixie Exp $"; +#endif + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv.h> +#include <string.h> + +/* These need to be in the same order as the nres.h:ns_flag enum. */ +struct _ns_flagdata _ns_flagdata[16] = { +	{ 0x8000, 15 },		/* qr. */ +	{ 0x7800, 11 },		/* opcode. */ +	{ 0x0400, 10 },		/* aa. */ +	{ 0x0200, 9 },		/* tc. */ +	{ 0x0100, 8 },		/* rd. */ +	{ 0x0080, 7 },		/* ra. */ +	{ 0x0040, 6 },		/* z. */ +	{ 0x0020, 5 },		/* ad. */ +	{ 0x0010, 4 },		/* cd. */ +	{ 0x000f, 0 },		/* rcode. */ +	{ 0x0000, 0 },		/* expansion (1/6). */ +	{ 0x0000, 0 },		/* expansion (2/6). */ +	{ 0x0000, 0 },		/* expansion (3/6). */ +	{ 0x0000, 0 },		/* expansion (4/6). */ +	{ 0x0000, 0 },		/* expansion (5/6). */ +	{ 0x0000, 0 },		/* expansion (6/6). */ +}; + +static int +skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) { +	const u_char *optr = ptr; + +	for ((void)NULL; count > 0; count--) { +		int b, rdlength; + +		b = dn_skipname(ptr, eom); +		if (b < 0) +			goto emsgsize; +		ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/; +		if (section != ns_s_qd) { +			if (ptr + NS_INT32SZ > eom) +				goto emsgsize; +			ptr += NS_INT32SZ/*TTL*/; +			if (ptr + NS_INT16SZ > eom) +				goto emsgsize; +			NS_GET16(rdlength, ptr); +			ptr += rdlength/*RData*/; +		} +	} +	if (ptr > eom) +		goto emsgsize; +	return (ptr - optr); + emsgsize: +	errno = EMSGSIZE; +	return (-1); +} + +int +ns_initparse(const u_char *msg, int msglen, ns_msg *handle) { +	const u_char *eom = msg + msglen; +	int i; + +	memset(handle, 0x5e, sizeof *handle); +	handle->_msg = msg; +	handle->_eom = eom; +	if (msg + NS_INT16SZ > eom) +		goto emsgsize; +	NS_GET16(handle->_id, msg); +	if (msg + NS_INT16SZ > eom) +		goto emsgsize; +	NS_GET16(handle->_flags, msg); +	for (i = 0; i < ns_s_max; i++) { +		if (msg + NS_INT16SZ > eom) +			goto emsgsize; +		NS_GET16(handle->_counts[i], msg); +	} +	for (i = 0; i < ns_s_max; i++) +		if (handle->_counts[i] == 0) +			handle->_sections[i] = NULL; +		else { +			int b = skiprr(msg, eom, (ns_sect)i, +				       handle->_counts[i]); + +			if (b < 0) +				return (-1); +			handle->_sections[i] = msg; +			msg += b; +		} +	if (msg != eom) +		goto emsgsize; +	handle->_sect = ns_s_max; +	handle->_rrnum = -1; +	handle->_ptr = NULL; +	return (0); + emsgsize: +	errno = EMSGSIZE; +	return (-1); +} + +int +ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) { +	int b; + +	/* Make section right. */ +	if (section < 0 || section >= ns_s_max) +		goto enodev; +	if ((int)section != (int)handle->_sect) { +		handle->_sect = section; +		handle->_rrnum = 0; +		handle->_ptr = handle->_sections[(int)section]; +	} + +	/* Make rrnum right. */ +	if (rrnum == -1) +		rrnum = handle->_rrnum; +	if (rrnum < 0 || rrnum >= handle->_counts[(int)section]) +		goto enodev; +	if (rrnum < handle->_rrnum) { +		handle->_rrnum = 0; +		handle->_ptr = handle->_sections[(int)section]; +	} +	 +	b = skiprr(handle->_msg, handle->_eom, section, +		   rrnum - handle->_rrnum); +	if (b < 0) +		return (-1); +	handle->_ptr += b; +	handle->_rrnum = rrnum; + +	/* Do the parse. */ +	b = dn_expand(handle->_msg, handle->_eom, +		      handle->_ptr, rr->name, NS_MAXDNAME); +	if (b < 0) +		return (-1); +	handle->_ptr += b; +	if (handle->_ptr + NS_INT16SZ > handle->_eom) +		goto emsgsize; +	NS_GET16(rr->type, handle->_ptr); +	if (handle->_ptr + NS_INT16SZ > handle->_eom) +		goto emsgsize; +	NS_GET16(rr->class, handle->_ptr); +	if (section == ns_s_qd) { +		rr->ttl = 0; +		rr->rdlength = 0; +		rr->rdata = NULL; +	} else { +		if (handle->_ptr + NS_INT32SZ > handle->_eom) +			goto emsgsize; +		NS_GET32(rr->ttl, handle->_ptr); +		if (handle->_ptr + NS_INT16SZ > handle->_eom) +			goto emsgsize; +		NS_GET16(rr->rdlength, handle->_ptr); +		if (handle->_ptr + rr->rdlength > handle->_eom) +			goto emsgsize; +		rr->rdata = handle->_ptr; +		handle->_ptr += rr->rdlength; +	} +	handle->_rrnum++; + +	/* All done. */ +	return (0); + enodev: +	errno = ENODEV; +	return (-1); + emsgsize: +	errno = EMSGSIZE; +	return (-1); +} diff --git a/lib/libc/net/ns_print.c b/lib/libc/net/ns_print.c new file mode 100644 index 000000000000..60b9017c3a76 --- /dev/null +++ b/lib/libc/net/ns_print.c @@ -0,0 +1,743 @@ +/* + * Copyright (c) 1996, 1998 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. + */ + +#ifndef lint +static char rcsid[] = "$Id: ns_print.c,v 8.4 1998/02/13 01:16:37 halley Exp $"; +#endif + +/* Import. */ + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <assert.h> +#include <errno.h> +#include <resolv.h> +#include <string.h> +#include <ctype.h> + +#define SPRINTF(x) ((size_t)sprintf x) + +/* Forward. */ + +static size_t	prune_origin(const char *name, const char *origin); +static int	charstr(const u_char *rdata, const u_char *edata, +			char **buf, size_t *buflen); +static int	addname(const u_char *msg, size_t msglen, +			const u_char **p, const char *origin, +			char **buf, size_t *buflen); +static void	addlen(size_t len, char **buf, size_t *buflen); +static int	addstr(const char *src, size_t len, +		       char **buf, size_t *buflen); +static int	addtab(size_t len, size_t target, int spaced, +		       char **buf, size_t *buflen); + +/* Macros. */ + +#define	T(x) \ +	do { \ +		if ((x) < 0) \ +			return (-1); \ +	} while (0) + +/* Public. */ + +/* + * int + * ns_sprintrr(handle, rr, name_ctx, origin, buf, buflen) + *	Convert an RR to presentation format. + * return: + *	Number of characters written to buf, or -1 (check errno). + */ +int +ns_sprintrr(const ns_msg *handle, const ns_rr *rr, +	    const char *name_ctx, const char *origin, +	    char *buf, size_t buflen) +{ +	int n; + +	n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle), +			 ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr), +			 ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr), +			 name_ctx, origin, buf, buflen); +	return (n); +} + +/* + * int + * ns_sprintrrf(msg, msglen, name, class, type, ttl, rdata, rdlen, + *	       name_ctx, origin, buf, buflen) + *	Convert the fields of an RR into presentation format. + * return: + *	Number of characters written to buf, or -1 (check errno). + */ +int +ns_sprintrrf(const u_char *msg, size_t msglen, +	    const char *name, ns_class class, ns_type type, +	    u_long ttl, const u_char *rdata, size_t rdlen, +	    const char *name_ctx, const char *origin, +	    char *buf, size_t buflen) +{ +	const char *obuf = buf; +	const u_char *edata = rdata + rdlen; +	int spaced = 0; + +	const char *comment; +	char tmp[100]; +	int len, x; + +	/* +	 * Owner. +	 */ +	if (name_ctx != NULL && strcasecmp(name_ctx, name) == 0) { +		T(addstr("\t\t\t", 3, &buf, &buflen)); +	} else { +		len = prune_origin(name, origin); +		if (len == 0) { +			T(addstr("@\t\t\t", 4, &buf, &buflen)); +		} else { +			T(addstr(name, len, &buf, &buflen)); +			/* Origin not used and no trailing dot? */ +			if ((!origin || !origin[0] || name[len] == '\0') && +			    name[len - 1] != '.') { +				T(addstr(".", 1, &buf, &buflen)); +				len++; +			} +			T(spaced = addtab(len, 24, spaced, &buf, &buflen)); +		} +	} + +	/* +	 * TTL, Class, Type. +	 */ +	T(x = ns_format_ttl(ttl, buf, buflen)); +	addlen(x, &buf, &buflen); +	len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type))); +	T(addstr(tmp, len, &buf, &buflen)); +	T(spaced = addtab(x + len, 16, spaced, &buf, &buflen)); + +	/* +	 * RData. +	 */ +	switch (type) { +	case ns_t_a: +		if (rdlen != NS_INADDRSZ) +			goto formerr; +		(void) inet_ntop(AF_INET, rdata, buf, buflen); +		addlen(strlen(buf), &buf, &buflen); +		break; + +	case ns_t_cname: +	case ns_t_mb: +	case ns_t_mg: +	case ns_t_mr: +	case ns_t_ns: +	case ns_t_ptr: +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); +		break; + +	case ns_t_hinfo: +	case ns_t_isdn: +		/* First word. */ +		T(len = charstr(rdata, edata, &buf, &buflen)); +		if (len == 0) +			goto formerr; +		rdata += len; +		T(addstr(" ", 1, &buf, &buflen)); + +		/* Second word. */ +		T(len = charstr(rdata, edata, &buf, &buflen)); +		if (len == 0) +			goto formerr; +		rdata += len; +		break; + +	case ns_t_soa: { +		u_long t; + +		/* Server name. */ +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); +		T(addstr(" ", 1, &buf, &buflen)); + +		/* Administrator name. */ +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); +		T(addstr(" (\n", 3, &buf, &buflen)); +		spaced = 0; + +		if ((edata - rdata) != 5*NS_INT32SZ) +			goto formerr; + +		/* Serial number. */ +		t = ns_get32(rdata);  rdata += NS_INT32SZ; +		T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); +		len = SPRINTF((tmp, "%lu", t)); +		T(addstr(tmp, len, &buf, &buflen)); +		T(spaced = addtab(len, 16, spaced, &buf, &buflen)); +		T(addstr("; serial\n", 9, &buf, &buflen)); +		spaced = 0; + +		/* Refresh interval. */ +		t = ns_get32(rdata);  rdata += NS_INT32SZ; +		T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); +		T(len = ns_format_ttl(t, buf, buflen)); +		addlen(len, &buf, &buflen); +		T(spaced = addtab(len, 16, spaced, &buf, &buflen)); +		T(addstr("; refresh\n", 10, &buf, &buflen)); +		spaced = 0; + +		/* Retry interval. */ +		t = ns_get32(rdata);  rdata += NS_INT32SZ; +		T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); +		T(len = ns_format_ttl(t, buf, buflen)); +		addlen(len, &buf, &buflen); +		T(spaced = addtab(len, 16, spaced, &buf, &buflen)); +		T(addstr("; retry\n", 8, &buf, &buflen)); +		spaced = 0; + +		/* Expiry. */ +		t = ns_get32(rdata);  rdata += NS_INT32SZ; +		T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); +		T(len = ns_format_ttl(t, buf, buflen)); +		addlen(len, &buf, &buflen); +		T(spaced = addtab(len, 16, spaced, &buf, &buflen)); +		T(addstr("; expiry\n", 9, &buf, &buflen)); +		spaced = 0; + +		/* Minimum TTL. */ +		t = ns_get32(rdata);  rdata += NS_INT32SZ; +		T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); +		T(len = ns_format_ttl(t, buf, buflen)); +		addlen(len, &buf, &buflen); +		T(addstr(" )", 2, &buf, &buflen)); +		T(spaced = addtab(len, 16, spaced, &buf, &buflen)); +		T(addstr("; minimum\n", 10, &buf, &buflen)); + +		break; +	    } + +	case ns_t_mx: +	case ns_t_afsdb: +	case ns_t_rt: { +		u_int t; + +		if (rdlen < NS_INT16SZ) +			goto formerr; + +		/* Priority. */ +		t = ns_get16(rdata); +		rdata += NS_INT16SZ; +		len = SPRINTF((tmp, "%u ", t)); +		T(addstr(tmp, len, &buf, &buflen)); + +		/* Target. */ +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + +		break; +	    } + +	case ns_t_px: { +		u_int t; + +		if (rdlen < NS_INT16SZ) +			goto formerr; + +		/* Priority. */ +		t = ns_get16(rdata); +		rdata += NS_INT16SZ; +		len = SPRINTF((tmp, "%u ", t)); +		T(addstr(tmp, len, &buf, &buflen)); + +		/* Name1. */ +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); +		T(addstr(" ", 1, &buf, &buflen)); + +		/* Name2. */ +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + +		break; +	    } + +	case ns_t_x25: +		T(len = charstr(rdata, edata, &buf, &buflen)); +		if (len == 0) +			goto formerr; +		rdata += len; +		break; + +	case ns_t_txt: +		while (rdata < edata) { +			T(len = charstr(rdata, edata, &buf, &buflen)); +			if (len == 0) +				goto formerr; +			rdata += len; +			if (rdata < edata) +				T(addstr(" ", 1, &buf, &buflen)); +		} +		break; + +	case ns_t_nsap: { +		char t[255*3]; + +		(void) inet_nsap_ntoa(rdlen, rdata, t); +		T(addstr(t, strlen(t), &buf, &buflen)); +		break; +	    } + +	case ns_t_aaaa: +		if (rdlen != NS_IN6ADDRSZ) +			goto formerr; +		(void) inet_ntop(AF_INET6, rdata, buf, buflen); +		addlen(strlen(buf), &buf, &buflen); +		break; + +	case ns_t_loc: { +		char t[255]; + +		/* XXX protocol format checking? */ +		(void) loc_ntoa(rdata, t); +		T(addstr(t, strlen(t), &buf, &buflen)); +		break; +	    } + +	case ns_t_naptr: { +		u_int order, preference; +		char t[50]; + +		if (rdlen < 2*NS_INT16SZ) +			goto formerr; + +		/* Order, Precedence. */ +		order = ns_get16(rdata);	rdata += NS_INT16SZ; +		preference = ns_get16(rdata);	rdata += NS_INT16SZ; +		len = SPRINTF((t, "%u %u ", order, preference)); +		T(addstr(t, len, &buf, &buflen)); + +		/* Flags. */ +		T(len = charstr(rdata, edata, &buf, &buflen)); +		if (len == 0) +			goto formerr; +		rdata += len; +		T(addstr(" ", 1, &buf, &buflen)); + +		/* Service. */ +		T(len = charstr(rdata, edata, &buf, &buflen)); +		if (len == 0) +			goto formerr; +		rdata += len; +		T(addstr(" ", 1, &buf, &buflen)); + +		/* Regexp. */ +		T(len = charstr(rdata, edata, &buf, &buflen)); +		if (len < 0) +			return (-1); +		if (len == 0) +			goto formerr; +		rdata += len; +		T(addstr(" ", 1, &buf, &buflen)); + +		/* Server. */ +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); +		break; +	    } + +	case ns_t_srv: { +		u_int priority, weight, port; +		char t[50]; + +		if (rdlen < NS_INT16SZ*3) +			goto formerr; + +		/* Priority, Weight, Port. */ +		priority = ns_get16(rdata);  rdata += NS_INT16SZ; +		weight   = ns_get16(rdata);  rdata += NS_INT16SZ; +		port     = ns_get16(rdata);  rdata += NS_INT16SZ; +		len = SPRINTF((t, "%u %u %u ", priority, weight, port)); +		T(addstr(t, len, &buf, &buflen)); + +		/* Server. */ +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); +		break; +	    } + +	case ns_t_minfo: +	case ns_t_rp: +		/* Name1. */ +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); +		T(addstr(" ", 1, &buf, &buflen)); + +		/* Name2. */ +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + +		break; + +	case ns_t_wks: { +		int n, lcnt; + +		if (rdlen < NS_INT32SZ + 1) +			goto formerr; + +		/* Address. */ +		(void) inet_ntop(AF_INET, rdata, buf, buflen); +		addlen(strlen(buf), &buf, &buflen); +		rdata += NS_INADDRSZ; + +		/* Protocol. */ +		len = SPRINTF((tmp, " %u ( ", *rdata)); +		T(addstr(tmp, len, &buf, &buflen)); +		rdata += NS_INT8SZ; + +		/* Bit map. */ +		n = 0; +		lcnt = 0; +		while (rdata < edata) { +			u_int c = *rdata++; +			do { +				if (c & 0200) { +					if (lcnt == 0) { +						T(addstr("\n\t\t\t\t", 5, +							 &buf, &buflen)); +						lcnt = 10; +						spaced = 0; +					} +					len = SPRINTF((tmp, "%d ", n)); +					T(addstr(tmp, len, &buf, &buflen)); +					lcnt--; +				} +				c <<= 1; +			} while (++n & 07); +		} +		T(addstr(")", 1, &buf, &buflen)); + +		break; +	    } + +	case ns_t_key: { +		char base64_key[NS_MD5RSA_MAX_BASE64]; +		u_int keyflags, protocol, algorithm; +		const char *leader; +		int n; + +		if (rdlen < NS_INT16SZ + NS_INT8SZ + NS_INT8SZ) +			goto formerr; + +		/* Key flags, Protocol, Algorithm. */ +		keyflags = ns_get16(rdata);  rdata += NS_INT16SZ; +		protocol = *rdata++; +		algorithm = *rdata++; +		len = SPRINTF((tmp, "0x%04x %u %u", +			       keyflags, protocol, algorithm)); +		T(addstr(tmp, len, &buf, &buflen)); + +		/* Public key data. */ +		len = b64_ntop(rdata, edata - rdata, +			       base64_key, sizeof base64_key); +		if (len < 0) +			goto formerr; +		if (len > 15) { +			T(addstr(" (", 2, &buf, &buflen)); +			leader = "\n\t\t"; +			spaced = 0; +		} else +			leader = " "; +		for (n = 0; n < len; n += 48) { +			T(addstr(leader, strlen(leader), &buf, &buflen)); +			T(addstr(base64_key + n, MIN(len - n, 48), +				 &buf, &buflen)); +		} +		if (len > 15) +			T(addstr(" )", 2, &buf, &buflen)); + +		break; +	    } + +	case ns_t_sig: { +		char base64_key[NS_MD5RSA_MAX_BASE64]; +		u_int type, algorithm, labels, footprint; +		const char *leader; +		u_long t; +		int n; + +		if (rdlen < 22) +			goto formerr; + +		/* Type covered, Algorithm, Label count, Original TTL. */ +	        type = ns_get16(rdata);  rdata += NS_INT16SZ; +		algorithm = *rdata++; +		labels = *rdata++; +		t = ns_get32(rdata);  rdata += NS_INT32SZ; +		len = SPRINTF((tmp, " %s %d %lu ", +			       p_type(type), algorithm, t)); +		T(addstr(tmp, len, &buf, &buflen)); +		if (labels != (u_int)dn_count_labels(name)) +			goto formerr; + +		/* Signature expiry. */ +		t = ns_get32(rdata);  rdata += NS_INT32SZ; +		len = SPRINTF((tmp, "%s ", p_secstodate(t))); +		T(addstr(tmp, len, &buf, &buflen)); + +		/* Time signed. */ +		t = ns_get32(rdata);  rdata += NS_INT32SZ; +		len = SPRINTF((tmp, "%s ", p_secstodate(t))); +		T(addstr(tmp, len, &buf, &buflen)); + +		/* Signature Footprint. */ +		footprint = ns_get16(rdata);  rdata += NS_INT16SZ; +		len = SPRINTF((tmp, "%u ", footprint)); +		T(addstr(tmp, len, &buf, &buflen)); + +		/* Signer's name. */ +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + +		/* Signature. */ +		len = b64_ntop(rdata, edata - rdata, +			       base64_key, sizeof base64_key); +		if (len > 15) { +			T(addstr(" (", 2, &buf, &buflen)); +			leader = "\n\t\t"; +			spaced = 0; +		} else +			leader = " "; +		if (len < 0) +			goto formerr; +		for (n = 0; n < len; n += 48) { +			T(addstr(leader, strlen(leader), &buf, &buflen)); +			T(addstr(base64_key + n, MIN(len - n, 48), +				 &buf, &buflen)); +		} +		if (len > 15) +			T(addstr(" )", 2, &buf, &buflen)); + +		break; +	    } + +	case ns_t_nxt: { +		int n, c; + +		/* Next domain name. */ +		T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + +		/* Type bit map. */ +		n = edata - rdata; +		for (c = 0; c < n*8; c++) +			if (NS_NXT_BIT_ISSET(c, rdata)) { +				len = SPRINTF((tmp, " %s", p_type(c))); +				T(addstr(tmp, len, &buf, &buflen)); +			} +		break; +	    } + +	default: +		comment = "unknown RR type"; +		goto hexify; +	} +	return (buf - obuf); + formerr: +	comment = "RR format error"; + hexify: { +	int n, m; +	char *p; + +	len = SPRINTF((tmp, "\\#(\t\t; %s", comment)); +	T(addstr(tmp, len, &buf, &buflen)); +	while (rdata < edata) { +		p = tmp; +		p += SPRINTF((p, "\n\t")); +		spaced = 0; +		n = MIN(16, edata - rdata); +		for (m = 0; m < n; m++) +			p += SPRINTF((p, "%02x ", rdata[m])); +		T(addstr(tmp, p - tmp, &buf, &buflen)); +		if (n < 16) { +			T(addstr(")", 1, &buf, &buflen)); +			T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen)); +		} +		p = tmp; +		p += SPRINTF((p, "; ")); +		for (m = 0; m < n; m++) +			*p++ = (isascii(rdata[m]) && isprint(rdata[m])) +				? rdata[m] +				: '.'; +		T(addstr(tmp, p - tmp, &buf, &buflen)); +		rdata += n; +	} +	return (buf - obuf); +    } +} + +/* Private. */ + +/* + * size_t + * prune_origin(name, origin) + *	Find out if the name is at or under the current origin. + * return: + *	Number of characters in name before start of origin, + *	or length of name if origin does not match. + * notes: + *	This function should share code with samedomain(). + */ +static size_t +prune_origin(const char *name, const char *origin) { +	const char *oname = name; + +	while (*name != '\0') { +		if (origin != NULL && strcasecmp(name, origin) == 0) +			return (name - oname - (name > oname)); +		while (*name != '\0') { +			if (*name == '\\') { +				name++; +				/* XXX need to handle \nnn form. */ +				if (*name == '\0') +					break; +			} else if (*name == '.') { +				name++; +				break; +			} +			name++; +		} +	} +	return (name - oname); +} + +/* + * int + * charstr(rdata, edata, buf, buflen) + *	Format a <character-string> into the presentation buffer. + * return: + *	Number of rdata octets consumed + *	0 for protocol format error + *	-1 for output buffer error + * side effects: + *	buffer is advanced on success. + */ +static int +charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) { +	const u_char *odata = rdata; +	size_t save_buflen = *buflen; +	char *save_buf = *buf; + +	if (addstr("\"", 1, buf, buflen) < 0) +		goto enospc; +	if (rdata < edata) { +		int n = *rdata; + +		if (rdata + 1 + n <= edata) { +			rdata++; +			while (n-- > 0) { +				if (strchr("\n\"\\", *rdata) != NULL) +					if (addstr("\\", 1, buf, buflen) < 0) +						goto enospc; +				if (addstr((const char *)rdata, 1, +					   buf, buflen) < 0) +					goto enospc; +				rdata++; +			} +		} +	} +	if (addstr("\"", 1, buf, buflen) < 0) +		goto enospc; +	return (rdata - odata); + enospc: +	errno = ENOSPC; +	*buf = save_buf; +	*buflen = save_buflen; +	return (-1); +} + +static int +addname(const u_char *msg, size_t msglen, +	const u_char **pp, const char *origin, +	char **buf, size_t *buflen) +{ +	size_t newlen, save_buflen = *buflen; +	char *save_buf = *buf; +	int n; + +	n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen); +	if (n < 0) +		goto enospc;	/* Guess. */ +	newlen = prune_origin(*buf, origin); +	if ((origin == NULL || origin[0] == '\0' || (*buf)[newlen] == '\0') && +	    (newlen == 0 || (*buf)[newlen - 1] != '.')) { +		/* No trailing dot. */ +		if (newlen + 2 > *buflen) +			goto enospc;	/* No room for ".\0". */ +		(*buf)[newlen++] = '.'; +		(*buf)[newlen] = '\0'; +	} +	if (newlen == 0) { +		/* Use "@" instead of name. */ +		if (newlen + 2 > *buflen) +			goto enospc;        /* No room for "@\0". */ +		(*buf)[newlen++] = '@'; +		(*buf)[newlen] = '\0'; +	} +	*pp += n; +	addlen(newlen, buf, buflen); +	**buf = '\0'; +	return (newlen); + enospc: +	errno = ENOSPC; +	*buf = save_buf; +	*buflen = save_buflen; +	return (-1); +} + +static void +addlen(size_t len, char **buf, size_t *buflen) { +	assert(len <= *buflen); +	*buf += len; +	*buflen -= len; +} + +static int +addstr(const char *src, size_t len, char **buf, size_t *buflen) { +	if (len > *buflen) { +		errno = ENOSPC; +		return (-1); +	} +	memcpy(*buf, src, len); +	addlen(len, buf, buflen); +	**buf = '\0'; +	return (0); +} + +static int +addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) { +	size_t save_buflen = *buflen; +	char *save_buf = *buf; +	int t; + +	if (spaced || len >= target - 1) { +		T(addstr("  ", 2, buf, buflen)); +		spaced = 1; +	} else { +		for (t = (target - len - 1) / 8; t >= 0; t--) +			if (addstr("\t", 1, buf, buflen) < 0) { +				*buflen = save_buflen; +				*buf = save_buf; +				return (-1); +			} +		spaced = 0; +	} +	return (spaced); +} diff --git a/lib/libc/net/ns_ttl.c b/lib/libc/net/ns_ttl.c new file mode 100644 index 000000000000..e62ae9940447 --- /dev/null +++ b/lib/libc/net/ns_ttl.c @@ -0,0 +1,151 @@ +/* + * 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. + */ + +#ifndef lint +static char rcsid[] = "$Id: ns_ttl.c,v 8.5 1998/02/13 01:16:38 halley Exp $"; +#endif + +/* Import. */ + +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#define SPRINTF(x) ((size_t)sprintf x) + +/* Forward. */ + +static int	fmt1(int t, char s, char **buf, size_t *buflen); + +/* Macros. */ + +#define T(x) if ((x) < 0) return (-1); else (void)NULL + +/* Public. */ + +int +ns_format_ttl(u_long src, char *dst, size_t dstlen) { +	char *odst = dst; +	int secs, mins, hours, days, weeks, x; +	char tmp[50], *p; + +	secs = src % 60;   src /= 60; +	mins = src % 60;   src /= 60; +	hours = src % 24;  src /= 24; +	days = src % 7;    src /= 7; +	weeks = src;       src = 0; + +	x = 0; +	if (weeks) { +		T(fmt1(weeks, 'W', &dst, &dstlen)); +		x++; +	} +	if (days) { +		T(fmt1(days, 'D', &dst, &dstlen)); +		x++; +	} +	if (hours) { +		T(fmt1(hours, 'H', &dst, &dstlen)); +		x++; +	} +	if (mins) { +		T(fmt1(mins, 'M', &dst, &dstlen)); +		x++; +	} +	if (secs || !(weeks || days || hours || mins)) { +		T(fmt1(secs, 'S', &dst, &dstlen)); +		x++; +	} + +	if (x > 1) { +		int ch; + +		for (p = odst; (ch = *p) != '\0'; p++) +			if (isascii(ch) && isupper(ch)) +				*p = tolower(ch); +	} + +	return (dst - odst); +} + +int +ns_parse_ttl(const char *src, u_long *dst) { +	u_long ttl, tmp; +	int ch, digits, dirty; + +	ttl = 0; +	tmp = 0; +	digits = 0; +	dirty = 0; +	while ((ch = *src++) != '\0') { +		if (!isascii(ch) || !isprint(ch)) +			goto einval; +		if (isdigit(ch)) { +			tmp *= 10; +			tmp += (ch - '0'); +			digits++; +			continue; +		} +		if (digits == 0) +			goto einval; +		if (islower(ch)) +			ch = toupper(ch); +		switch (ch) { +		case 'W':  tmp *= 7; +		case 'D':  tmp *= 24; +		case 'H':  tmp *= 60; +		case 'M':  tmp *= 60; +		case 'S':  break; +		default:   goto einval; +		} +		ttl += tmp; +		tmp = 0; +		digits = 0; +		dirty = 1; +	} +	if (digits > 0) { +		if (dirty) +			goto einval; +		else +			ttl += tmp; +	} +	*dst = ttl; +	return (0); + + einval: +	errno = EINVAL; +	return (-1); +} + +/* Private. */ + +static int +fmt1(int t, char s, char **buf, size_t *buflen) { +	char tmp[50]; +	size_t len; + +	len = SPRINTF((tmp, "%d%c", t, s)); +	if (len + 1 > *buflen) +		return (-1); +	strcpy(*buf, tmp); +	*buf += len; +	*buflen -= len; +	return (0); +} diff --git a/lib/libc/net/nsap_addr.c b/lib/libc/net/nsap_addr.c index b0c6433e558d..1db7dd775926 100644 --- a/lib/libc/net/nsap_addr.c +++ b/lib/libc/net/nsap_addr.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 1996 by Internet Software Consortium. + * Copyright (c) 1996, 1998 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 @@ -16,13 +16,14 @@   */  #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$Id$"; +static char rcsid[] = "$Id: nsap_addr.c,v 1.4 1997/02/22 15:00:27 peter Exp $";  #endif /* LIBC_SCCS and not lint */  #include <sys/types.h>  #include <sys/param.h>  #include <sys/socket.h>  #include <netinet/in.h> +#include <arpa/inet.h>  #include <arpa/nameser.h>  #include <ctype.h>  #include <resolv.h> @@ -40,10 +41,10 @@ inet_nsap_addr(ascii, binary, maxlen)  	u_char *binary;  	int maxlen;  { -	register u_char c, nib; +	u_char c, nib;  	u_int len = 0; -	while ((c = *ascii++) != '\0' && len < maxlen) { +	while ((c = *ascii++) != '\0' && len < (u_int)maxlen) {  		if (c == '.' || c == '+' || c == '/')  			continue;  		if (!isascii(c)) @@ -52,7 +53,8 @@ inet_nsap_addr(ascii, binary, maxlen)  			c = toupper(c);  		if (isxdigit(c)) {  			nib = xtob(c); -			if ((c = *ascii++) != '\0') { +			c = *ascii++; +			if (c != '\0') {  				c = toupper(c);  				if (isxdigit(c)) {  					*binary++ = (nib << 4) | xtob(c); diff --git a/lib/libc/net/res_comp.c b/lib/libc/net/res_comp.c index 8cd74696e348..de14f072c2f1 100644 --- a/lib/libc/net/res_comp.c +++ b/lib/libc/net/res_comp.c @@ -1,6 +1,4 @@  /* - * ++Copyright++ 1985, 1993 - * -   * Copyright (c) 1985, 1993   *    The Regents of the University of California.  All rights reserved.   *  @@ -31,7 +29,9 @@   * 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. - * - + */ + +/*   * Portions Copyright (c) 1993 by Digital Equipment Corporation.   *    * Permission to use, copy, modify, and distribute this software for any @@ -49,40 +49,42 @@   * 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. - * - - * --Copyright-- + */ + +/* + * Portions 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 sccsid[] = "@(#)res_comp.c	8.1 (Berkeley) 6/4/93"; -static char orig_rcsid[] = "From: Id: res_comp.c,v 8.13 1998/04/07 04:24:06 vixie Exp $"; -static char rcsid[] = "$Id: res_comp.c,v 1.12 1997/06/27 08:22:02 peter Exp $"; +static char orig_rcsid[] = "From: Id: res_comp.c,v 8.11 1997/05/21 19:31:04 halley Exp $"; +static char rcsid[] = "$Id: res_comp.c,v 1.13 1998/05/02 13:10:56 peter Exp $";  #endif /* LIBC_SCCS and not lint */  #include <sys/types.h>  #include <sys/param.h>  #include <netinet/in.h>  #include <arpa/nameser.h> - -#include <stdio.h> -#include <resolv.h>  #include <ctype.h> -#include <errno.h> - -#include <unistd.h> +#include <resolv.h> +#include <stdio.h>  #include <string.h> +#include <unistd.h> -static int	ns_name_ntop __P((const u_char *, char *, size_t)); -static int	ns_name_pton __P((const char *, u_char *, size_t)); -static int	ns_name_unpack __P((const u_char *, const u_char *, -				    const u_char *, u_char *, size_t)); -static int	ns_name_pack __P((const u_char *, u_char *, int, -				  const u_char **, const u_char **)); -static int	ns_name_uncompress __P((const u_char *, const u_char *, -					const u_char *, char *, size_t)); -static int	ns_name_compress __P((const char *, u_char *, size_t, -				      const u_char **, const u_char **)); -static int	ns_name_skip __P((const u_char **, const u_char *)); +#define BIND_4_COMPAT  /*   * Expand compressed domain name 'comp_dn' to full domain name. @@ -120,7 +122,7 @@ dn_comp(const char *src, u_char *dst, int dstsiz,   * Skip over a compressed domain name. Return the size or -1.   */  int -__dn_skipname(const u_char *ptr, const u_char *eom) { +dn_skipname(const u_char *ptr, const u_char *eom) {  	const u_char *saveptr = ptr;  	if (ns_name_skip(&ptr, eom) == -1) @@ -161,7 +163,7 @@ res_hnok(dn)  		int nch = *dn++;  		if (periodchar(ch)) { -			NULL; +			(void)NULL;  		} else if (periodchar(pch)) {  			if (!borderchar(ch))  				return (0); @@ -206,7 +208,7 @@ res_mailok(dn)  	/* "." is a valid missing representation */  	if (*dn == '\0') -		return(1); +		return (1);  	/* otherwise <label>.<hostname> */  	while ((ch = *dn++) != '\0') { @@ -221,7 +223,7 @@ res_mailok(dn)  	}  	if (periodchar(ch))  		return (res_hnok(dn)); -	return(0); +	return (0);  }  /* @@ -240,683 +242,17 @@ res_dnok(dn)  	return (1);  } +#ifdef BIND_4_COMPAT  /* - * Routines to insert/extract short/long's. - */ - -u_int16_t -_getshort(msgp) -	register const u_char *msgp; -{ -	register u_int16_t u; - -	GETSHORT(u, msgp); -	return (u); -} - -u_int32_t -_getlong(msgp) -	register const u_char *msgp; -{ -	register u_int32_t u; - -	GETLONG(u, msgp); -	return (u); -} - -void -#if defined(__STDC__) || defined(__cplusplus) -__putshort(register u_int16_t s, register u_char *msgp)	/* must match proto */ -#else -__putshort(s, msgp) -	register u_int16_t s; -	register u_char *msgp; -#endif -{ -	PUTSHORT(s, msgp); -} - -void -__putlong(l, msgp) -	register u_int32_t l; -	register u_char *msgp; -{ -	PUTLONG(l, msgp); -} - -/* ++ From BIND 8.1.1. ++ */ -/* - * 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. - */ - -/*"Id: ns_name.c,v 1.1 1997/12/13 02:41:13 vixie Exp vixie"*/ - -/*#include "port_before.h"*/ - -/*#include <sys/types.h>*/ - -/*#include <netinet/in.h>*/ -/*#include <arpa/nameser.h>*/ - -/*#include <errno.h>*/ -/*#include <resolv.h>*/ -/*#include <string.h>*/ - -/*#include "port_after.h"*/ - -#define NS_CMPRSFLGS	0xc0	/* Flag bits indicating name compression. */ -#define NS_MAXCDNAME	255	/* maximum compressed domain name */ - -/* Data. */ - -static char		digits[] = "0123456789"; - -/* Forward. */ - -static int		special(int); -static int		printable(int); -static int		dn_find(const u_char *, const u_char *, -				const u_char * const *, -				const u_char * const *); - -/* Public. */ - -/* - * ns_name_ntop(src, dst, dstsiz) - *	Convert an encoded domain name to printable ascii as per RFC1035. - * return: - *	Number of bytes written to buffer, or -1 (with errno set) - * notes: - *	The root is returned as "." - *	All other domains are returned in non absolute form - */ -static int -ns_name_ntop(src, dst, dstsiz) -	const u_char *src; -	char *dst; -	size_t dstsiz; -{ -	const u_char *cp; -	char *dn, *eom; -	u_char c; -	u_int n; - -	cp = src; -	dn = dst; -	eom = dst + dstsiz; - -	while ((n = *cp++) != 0) { -		if ((n & NS_CMPRSFLGS) != 0) { -			/* Some kind of compression pointer. */ -			errno = EMSGSIZE; -			return (-1); -		} -		if (dn != dst) { -			if (dn >= eom) { -				errno = EMSGSIZE; -				return (-1); -			} -			*dn++ = '.'; -		} -		if (dn + n >= eom) { -			errno = EMSGSIZE; -			return (-1); -		} -		for ((void)NULL; n > 0; n--) { -			c = *cp++; -			if (special(c)) { -				if (dn + 1 >= eom) { -					errno = EMSGSIZE; -					return (-1); -				} -				*dn++ = '\\'; -				*dn++ = (char)c; -			} else if (!printable(c)) { -				if (dn + 3 >= eom) { -					errno = EMSGSIZE; -					return (-1); -				} -				*dn++ = '\\'; -				*dn++ = digits[c / 100]; -				*dn++ = digits[(c % 100) / 10]; -				*dn++ = digits[c % 10]; -			} else { -				if (dn >= eom) { -					errno = EMSGSIZE; -					return (-1); -				} -				*dn++ = (char)c; -			} -		} -	} -	if (dn == dst) { -		if (dn >= eom) { -			errno = EMSGSIZE; -			return (-1); -		} -		*dn++ = '.'; -	} -	if (dn >= eom) { -		errno = EMSGSIZE; -		return (-1); -	} -	*dn++ = '\0'; -	return (dn - dst); -} - -/* - * ns_name_pton(src, dst, dstsiz) - *	Convert a ascii string into an encoded domain name as per RFC1035. - * return: - *	-1 if it fails - *	1 if string was fully qualified - *	0 is string was not fully qualified - * notes: - *	Enforces label and domain length limits. - */ - -static int -ns_name_pton(src, dst, dstsiz) -	const char *src; -	u_char *dst; -	size_t dstsiz; -{ -	u_char *label, *bp, *eom; -	int c, n, escaped; -	char *cp; - -	escaped = 0; -	bp = dst; -	eom = dst + dstsiz; -	label = bp++; - -	while ((c = *src++) != 0) { -		if (escaped) { -			if ((cp = strchr(digits, c)) != NULL) { -				n = (cp - digits) * 100; -				if ((c = *src++) == 0 || -				    (cp = strchr(digits, c)) == NULL) { -					errno = EMSGSIZE; -					return (-1); -				} -				n += (cp - digits) * 10; -				if ((c = *src++) == 0 || -				    (cp = strchr(digits, c)) == NULL) { -					errno = EMSGSIZE; -					return (-1); -				} -				n += (cp - digits); -				if (n > 255) { -					errno = EMSGSIZE; -					return (-1); -				} -				c = n; -			} -			escaped = 0; -		} else if (c == '\\') { -			escaped = 1; -			continue; -		} else if (c == '.') { -			c = (bp - label - 1); -			if ((c & NS_CMPRSFLGS) != 0) {	/* Label too big. */ -				errno = EMSGSIZE; -				return (-1); -			} -			if (label >= eom) { -				errno = EMSGSIZE; -				return (-1); -			} -			*label = c; -			/* Fully qualified ? */ -			if (*src == '\0') { -				if (c != 0) { -					if (bp >= eom) { -						errno = EMSGSIZE; -						return (-1); -					} -					*bp++ = '\0'; -				} -				if ((bp - dst) > MAXCDNAME) { -					errno = EMSGSIZE; -					return (-1); -				} -				return (1); -			} -			if (c == 0) { -				errno = EMSGSIZE; -				return (-1); -			} -			label = bp++; -			continue; -		} -		if (bp >= eom) { -			errno = EMSGSIZE; -			return (-1); -		} -		*bp++ = (u_char)c; -	} -	c = (bp - label - 1); -	if ((c & NS_CMPRSFLGS) != 0) {		/* Label too big. */ -		errno = EMSGSIZE; -		return (-1); -	} -	if (label >= eom) { -		errno = EMSGSIZE; -		return (-1); -	} -	*label = c; -	if (c != 0) { -		if (bp >= eom) { -			errno = EMSGSIZE; -			return (-1); -		} -		*bp++ = 0; -	} -	if ((bp - dst) > MAXCDNAME) {	/* src too big */ -		errno = EMSGSIZE; -		return (-1); -	} -	return (0); -} - -/* - * ns_name_unpack(msg, eom, src, dst, dstsiz) - *	Unpack a domain name from a message, source may be compressed. - * return: - *	-1 if it fails, or consumed octets if it succeeds. - */ -static int -ns_name_unpack(msg, eom, src, dst, dstsiz) -	const u_char *msg; -	const u_char *eom; -	const u_char *src; -	u_char *dst; -	size_t dstsiz; -{ -	const u_char *srcp, *dstlim; -	u_char *dstp; -	int n, c, len, checked; - -	len = -1; -	checked = 0; -	dstp = dst; -	srcp = src; -	dstlim = dst + dstsiz; -	if (srcp < msg || srcp >= eom) { -		errno = EMSGSIZE; -		return (-1); -	} -	/* Fetch next label in domain name. */ -	while ((n = *srcp++) != 0) { -		/* Check for indirection. */ -		switch (n & NS_CMPRSFLGS) { -		case 0: -			/* Limit checks. */ -			if (dstp + n + 1 >= dstlim || srcp + n >= eom) { -				errno = EMSGSIZE; -				return (-1); -			} -			checked += n + 1; -			*dstp++ = n; -			memcpy(dstp, srcp, n); -			dstp += n; -			srcp += n; -			break; - -		case NS_CMPRSFLGS: -			if (srcp >= eom) { -				errno = EMSGSIZE; -				return (-1); -			} -			if (len < 0) -				len = srcp - src + 1; -			srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); -			if (srcp < msg || srcp >= eom) {  /* Out of range. */ -				errno = EMSGSIZE; -				return (-1); -			} -			checked += 2; -			/* -			 * Check for loops in the compressed name; -			 * if we've looked at the whole message, -			 * there must be a loop. -			 */ -			if (checked >= eom - msg) { -				errno = EMSGSIZE; -				return (-1); -			} -			break; - -		default: -			errno = EMSGSIZE; -			return (-1);			/* flag error */ -		} -	} -	*dstp = '\0'; -	if (len < 0) -		len = srcp - src; -	return (len); -} - -/* - * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr) - *	Pack domain name 'domain' into 'comp_dn'. - * return: - *	Size of the compressed name, or -1. - * notes: - *	'dnptrs' is an array of pointers to previous compressed names. - *	dnptrs[0] is a pointer to the beginning of the message. The array - *	ends with NULL. - *	'lastdnptr' is a pointer to the end of the array pointed to - *	by 'dnptrs'. - * Side effects: - *	The list of pointers in dnptrs is updated for labels inserted into - *	the message as we compress the name.  If 'dnptr' is NULL, we don't - *	try to compress names. If 'lastdnptr' is NULL, we don't update the - *	list. + * This module must export the following externally-visible symbols: + *    ___putlong + *    ___putshort + *    __getlong + *    __getshort + * Note that one _ comes from C and the others come from us.   */ -static int -ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr) -	const u_char *src; -	u_char *dst; -	int dstsiz; -	const u_char **dnptrs; -	const u_char **lastdnptr; -{ -	u_char *dstp; -	const u_char **cpp, **lpp, *eob, *msg; -	const u_char *srcp; -	int n, l; - -	srcp = src; -	dstp = dst; -	eob = dstp + dstsiz; -	lpp = cpp = NULL; -	if (dnptrs != NULL) { -		if ((msg = *dnptrs++) != NULL) { -			for (cpp = dnptrs; *cpp != NULL; cpp++) -				(void)NULL; -			lpp = cpp;	/* end of list to search */ -		} -	} else -		msg = NULL; - -	/* make sure the domain we are about to add is legal */ -	l = 0; -	do { -		n = *srcp; -		if ((n & NS_CMPRSFLGS) != 0) { -			errno = EMSGSIZE; -			return (-1); -		} -		l += n + 1; -		if (l > MAXCDNAME) { -			errno = EMSGSIZE; -			return (-1); -		} -		srcp += n + 1; -	} while (n != 0); - -	srcp = src; -	do { -		/* Look to see if we can use pointers. */ -		n = *srcp; -		if (n != 0 && msg != NULL) { -			l = dn_find(srcp, msg, (const u_char * const *)dnptrs, -				    (const u_char * const *)lpp); -			if (l >= 0) { -				if (dstp + 1 >= eob) { -					errno = EMSGSIZE; -					return (-1); -				} -				*dstp++ = (l >> 8) | NS_CMPRSFLGS; -				*dstp++ = l % 256; -				return (dstp - dst); -			} -			/* Not found, save it. */ -			if (lastdnptr != NULL && cpp < lastdnptr - 1 && -			    (dstp - msg) < 0x4000) { -				*cpp++ = dstp; -				*cpp = NULL; -			} -		} -		/* copy label to buffer */ -		if (n & NS_CMPRSFLGS) {		/* Should not happen. */ -			errno = EMSGSIZE; -			return (-1); -		} -		if (dstp + 1 + n >= eob) { -			errno = EMSGSIZE; -			return (-1); -		} -		memcpy(dstp, srcp, n + 1); -		srcp += n + 1; -		dstp += n + 1; -	} while (n != 0); - -	if (dstp > eob) { -		if (msg != NULL) -			*lpp = NULL; -		errno = EMSGSIZE; -		return (-1); -	}  -	return (dstp - dst); -} - -/* - * ns_name_uncompress(msg, eom, src, dst, dstsiz) - *	Expand compressed domain name to presentation format. - * return: - *	Number of bytes read out of `src', or -1 (with errno set). - * note: - *	Root domain returns as "." not "". - */ -static int -ns_name_uncompress(msg, eom, src, dst, dstsiz) -	const u_char *msg; -	const u_char *eom; -	const u_char *src; -	char *dst; -	size_t dstsiz; -{ -	u_char tmp[NS_MAXCDNAME]; -	int n; -	 -	if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1) -		return (-1); -	if (ns_name_ntop(tmp, dst, dstsiz) == -1) -		return (-1); -	return (n); -} - -/* - * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr) - *	Compress a domain name into wire format, using compression pointers. - * return: - *	Number of bytes consumed in `dst' or -1 (with errno set). - * notes: - *	'dnptrs' is an array of pointers to previous compressed names. - *	dnptrs[0] is a pointer to the beginning of the message. - *	The list ends with NULL.  'lastdnptr' is a pointer to the end of the - *	array pointed to by 'dnptrs'. Side effect is to update the list of - *	pointers for labels inserted into the message as we compress the name. - *	If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' - *	is NULL, we don't update the list. - */ -static int -ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr) -	const char *src; -	u_char *dst; -	size_t dstsiz; -	const u_char **dnptrs; -	const u_char **lastdnptr; -{ -	u_char tmp[NS_MAXCDNAME]; - -	if (ns_name_pton(src, tmp, sizeof tmp) == -1) -		return (-1); -	return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr)); -} - -/* - * ns_name_skip(ptrptr, eom) - *	Advance *ptrptr to skip over the compressed name it points at. - * return: - *	0 on success, -1 (with errno set) on failure. - */ -static int -ns_name_skip(ptrptr, eom) -	const u_char **ptrptr; -	const u_char *eom; -{ -	const u_char *cp; -	u_int n; - -	cp = *ptrptr; -	while (cp < eom && (n = *cp++) != 0) { -		/* Check for indirection. */ -		switch (n & NS_CMPRSFLGS) { -		case 0:			/* normal case, n == len */ -			cp += n; -			continue; -		case NS_CMPRSFLGS:	/* indirection */ -			cp++; -			break; -		default:		/* illegal type */ -			errno = EMSGSIZE; -			return (-1); -		} -		break; -	} -	if (cp > eom) { -		errno = EMSGSIZE; -		return (-1); -	} -	*ptrptr = cp; -	return (0); -} - -/* Private. */ - -/* - * special(ch) - *	Thinking in noninternationalized USASCII (per the DNS spec), - *	is this characted special ("in need of quoting") ? - * return: - *	boolean. - */ -static int -special(ch) -	int ch; -{ -	switch (ch) { -	case 0x22: /* '"' */ -	case 0x2E: /* '.' */ -	case 0x3B: /* ';' */ -	case 0x5C: /* '\\' */ -	/* Special modifiers in zone files. */ -	case 0x40: /* '@' */ -	case 0x24: /* '$' */ -		return (1); -	default: -		return (0); -	} -} - -/* - * printable(ch) - *	Thinking in noninternationalized USASCII (per the DNS spec), - *	is this character visible and not a space when printed ? - * return: - *	boolean. - */ -static int -printable(ch) -	int ch; -{ -	return (ch > 0x20 && ch < 0x7f); -} - -/* - *	Thinking in noninternationalized USASCII (per the DNS spec), - *	convert this character to lower case if it's upper case. - */ -static int -mklower(ch) -	int ch; -{ -	if (ch >= 0x41 && ch <= 0x5A) -		return (ch + 0x20); -	return (ch); -} - -/* - * dn_find(domain, msg, dnptrs, lastdnptr) - *	Search for the counted-label name in an array of compressed names. - * return: - *	offset from msg if found, or -1. - * notes: - *	dnptrs is the pointer to the first name on the list, - *	not the pointer to the start of the message. - */ -static int -dn_find(domain, msg, dnptrs, lastdnptr) -	const u_char *domain; -	const u_char *msg; -	const u_char * const *dnptrs; -	const u_char * const *lastdnptr; -{ -	const u_char *dn, *cp, *sp; -	const u_char * const *cpp; -	u_int n; - -	for (cpp = dnptrs; cpp < lastdnptr; cpp++) { -		dn = domain; -		sp = cp = *cpp; -		while ((n = *cp++) != 0) { -			/* -			 * check for indirection -			 */ -			switch (n & NS_CMPRSFLGS) { -			case 0:			/* normal case, n == len */ -				if (n != *dn++) -					goto next; -				for ((void)NULL; n > 0; n--) -					if (mklower(*dn++) != mklower(*cp++)) -						goto next; -				/* Is next root for both ? */ -				if (*dn == '\0' && *cp == '\0') -					return (sp - msg); -				if (*dn) -					continue; -				goto next; - -			case NS_CMPRSFLGS:	/* indirection */ -				cp = msg + (((n & 0x3f) << 8) | *cp); -				break; - -			default:	/* illegal type */ -				errno = EMSGSIZE; -				return (-1); -			} -		} - next: ; -	} -	errno = ENOENT; -	return (-1); -} - -/* -- From BIND 8.1.1. -- */ +void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); } +void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); } +u_int32_t _getlong(const u_char *src) { return (ns_get32(src)); } +u_int16_t _getshort(const u_char *src) { return (ns_get16(src)); } +#endif /*BIND_4_COMPAT*/ diff --git a/lib/libc/net/res_config.h b/lib/libc/net/res_config.h index f29246a57e8f..644e7d796add 100644 --- a/lib/libc/net/res_config.h +++ b/lib/libc/net/res_config.h @@ -1,8 +1,8 @@  #define	DEBUG	1	/* enable debugging code (needed for dig) */ -#undef	ALLOW_T_UNSPEC	/* enable the "unspec" RR type for old athena */  #define	RESOLVSORT	/* allow sorting of addresses in gethostbyname */  #define	RFC1535		/* comply with RFC1535 (STRONGLY reccomended by vixie)*/  #undef	USELOOPBACK	/* res_init() bind to localhost */  #undef	SUNSECURITY	/* verify gethostbyaddr() calls - WE DONT NEED IT  */  #define MULTI_PTRS_ARE_ALIASES 1 /* fold multiple PTR records into aliases */  #define	CHECK_SRVR_ADDR 1 /* confirm that the server requested sent the reply */ +#define BIND_UPDATE 1	/* update support */ diff --git a/lib/libc/net/res_data.c b/lib/libc/net/res_data.c index df0e0ddc9e48..b79e3abdce43 100644 --- a/lib/libc/net/res_data.c +++ b/lib/libc/net/res_data.c @@ -1,60 +1,22 @@  /* - * ++Copyright++ 1995 - * - - * Copyright (c) 1995 - *    The Regents of the University of California.  All rights reserved. - *  - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - *    notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - * 	This product includes software developed by the University of - * 	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - *    may be used to endorse or promote products derived from this software - *    without specific prior written permission. - *  - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - * - - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - *  + * Copyright (c) 1995,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, and that - * the name of Digital Equipment Corporation not be used in advertising or - * publicity pertaining to distribution of the document or software without - * specific, written prior permission. - *  - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT - * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * 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. - * - - * --Copyright--   */  #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$Id$"; +static char rcsid[] = "$Id: res_data.c,v 1.5 1997/02/22 15:00:30 peter Exp $";  #endif /* LIBC_SCCS and not lint */  #include <sys/types.h> @@ -64,13 +26,14 @@ static char rcsid[] = "$Id$";  #include <netinet/in.h>  #include <arpa/inet.h>  #include <arpa/nameser.h> - -#include <stdio.h>  #include <ctype.h>  #include <resolv.h> -#include <unistd.h> +#include <stdio.h>  #include <stdlib.h>  #include <string.h> +#include <unistd.h> + +#include "res_config.h"  const char *_res_opcodes[] = {  	"QUERY", @@ -78,15 +41,15 @@ const char *_res_opcodes[] = {  	"CQUERYM",  	"CQUERYU",	/* experimental */  	"NOTIFY",	/* experimental */ -	"5", +	"UPDATE",  	"6",  	"7",  	"8", -	"UPDATEA", -	"UPDATED", -	"UPDATEDA", -	"UPDATEM", -	"UPDATEMA", +	"9", +	"10", +	"11", +	"12", +	"13",  	"ZONEINIT",  	"ZONEREF",  }; @@ -98,14 +61,23 @@ const char *_res_resultcodes[] = {  	"NXDOMAIN",  	"NOTIMP",  	"REFUSED", -	"6", -	"7", -	"8", -	"9", -	"10", +	"YXDOMAIN", +	"YXRRSET", +	"NXRRSET", +	"NOTAUTH", +	"ZONEERR",  	"11",  	"12",  	"13",  	"14",  	"NOCHANGE",  }; + +#ifdef BIND_UPDATE +const char *_res_sectioncodes[] = { +	"ZONE", +	"PREREQUISITES", +	"UPDATE", +	"ADDITIONAL", +}; +#endif diff --git a/lib/libc/net/res_debug.c b/lib/libc/net/res_debug.c index 06b8b427325a..d2e94cc03063 100644 --- a/lib/libc/net/res_debug.c +++ b/lib/libc/net/res_debug.c @@ -1,7 +1,5 @@  /* - * ++Copyright++ 1985, 1990, 1993 - * - - * Copyright (c) 1985, 1990, 1993 + * Copyright (c) 1985   *    The Regents of the University of California.  All rights reserved.   *    * Redistribution and use in source and binary forms, with or without @@ -31,7 +29,9 @@   * 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. - * - + */ + +/*   * Portions Copyright (c) 1993 by Digital Equipment Corporation.   *    * Permission to use, copy, modify, and distribute this software for any @@ -49,7 +49,9 @@   * 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. - * - + */ + +/*   * Portions Copyright (c) 1995 by International Business Machines, Inc.   *   * International Business Machines, Inc. (hereinafter called IBM) grants @@ -72,184 +74,127 @@   * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING   * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN   * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. - * --Copyright-- + */ + +/* + * Portions 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 sccsid[] = "@(#)res_debug.c	8.1 (Berkeley) 6/4/93"; -static char orig_rcsid[] = "From: Id: res_debug.c,v 8.20 1997/06/01 20:34:37 vixie Exp"; -static char rcsid[] = "$Id: res_debug.c,v 1.13 1997/02/22 15:00:31 peter Exp $"; +static char rcsid[] = "$Id: res_debug.c,v 8.20 1998/02/13 01:11:34 halley Exp $";  #endif /* LIBC_SCCS and not lint */ -#include "res_config.h" - -#include <sys/param.h>  #include <sys/types.h> +#include <sys/param.h>  #include <sys/socket.h> +  #include <netinet/in.h>  #include <arpa/inet.h>  #include <arpa/nameser.h>  #include <ctype.h> +#include <errno.h> +#include <math.h>  #include <netdb.h>  #include <resolv.h>  #include <stdio.h> -#include <time.h> -  #include <stdlib.h>  #include <string.h> +#include <time.h> + +#define SPRINTF(x) sprintf x  extern const char *_res_opcodes[];  extern const char *_res_resultcodes[]; +extern const char *_res_sectioncodes[]; -/* XXX: we should use getservbyport() instead. */ -static const char * -dewks(wks) -	int wks; -{ -	static char nbuf[20]; - -	switch (wks) { -	case 5: return "rje"; -	case 7: return "echo"; -	case 9: return "discard"; -	case 11: return "systat"; -	case 13: return "daytime"; -	case 15: return "netstat"; -	case 17: return "qotd"; -	case 19: return "chargen"; -	case 20: return "ftp-data"; -	case 21: return "ftp"; -	case 23: return "telnet"; -	case 25: return "smtp"; -	case 37: return "time"; -	case 39: return "rlp"; -	case 42: return "name"; -	case 43: return "whois"; -	case 53: return "domain"; -	case 57: return "apts"; -	case 59: return "apfs"; -	case 67: return "bootps"; -	case 68: return "bootpc"; -	case 69: return "tftp"; -	case 77: return "rje"; -	case 79: return "finger"; -	case 87: return "link"; -	case 95: return "supdup"; -	case 100: return "newacct"; -	case 101: return "hostnames"; -	case 102: return "iso-tsap"; -	case 103: return "x400"; -	case 104: return "x400-snd"; -	case 105: return "csnet-ns"; -	case 109: return "pop-2"; -	case 111: return "sunrpc"; -	case 113: return "auth"; -	case 115: return "sftp"; -	case 117: return "uucp-path"; -	case 119: return "nntp"; -	case 121: return "erpc"; -	case 123: return "ntp"; -	case 133: return "statsrv"; -	case 136: return "profile"; -	case 144: return "NeWS"; -	case 161: return "snmp"; -	case 162: return "snmp-trap"; -	case 170: return "print-srv"; -	default: (void) sprintf(nbuf, "%d", wks); return (nbuf); -	} -} +/* + * Print the current options. + */ +void +fp_resstat(struct __res_state *statp, FILE *file) { +	u_long mask; -/* XXX: we should use getprotobynumber() instead. */ -static const char * -deproto(protonum) -	int protonum; -{ -	static char nbuf[20]; - -	switch (protonum) { -	case 1: return "icmp"; -	case 2: return "igmp"; -	case 3: return "ggp"; -	case 5: return "st"; -	case 6: return "tcp"; -	case 7: return "ucl"; -	case 8: return "egp"; -	case 9: return "igp"; -	case 11: return "nvp-II"; -	case 12: return "pup"; -	case 16: return "chaos"; -	case 17: return "udp"; -	default: (void) sprintf(nbuf, "%d", protonum); return (nbuf); -	} +	fprintf(file, ";; res options:"); +	if (!statp) +		statp = &_res; +	for (mask = 1;  mask != 0;  mask <<= 1) +		if (statp->options & mask) +			fprintf(file, " %s", p_option(mask)); +	putc('\n', file);  } -static const u_char * -do_rrset(msg, len, cp, cnt, pflag, file, hs) -	int cnt, pflag, len; -	const u_char *cp, *msg; -	const char *hs; -	FILE *file; -{ -	int n; -	int sflag; +static void +do_section(ns_msg *handle, ns_sect section, int pflag, FILE *file) { +	int n, sflag, rrnum; +	char buf[2048];	/* XXX need to malloc */ +	ns_opcode opcode; +	ns_rr rr;  	/*  	 * Print answer records.  	 */  	sflag = (_res.pfcode & pflag); -	if ((n = ntohs(cnt)) != 0) { -		if ((!_res.pfcode) || -		    ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) -			fprintf(file, hs); -		while (--n >= 0) { -			if ((!_res.pfcode) || sflag) { -				cp = p_rr(cp, msg, file); -			} else { -				unsigned int dlen; -				cp += __dn_skipname(cp, cp + MAXCDNAME); -				cp += INT16SZ; -				cp += INT16SZ; -				cp += INT32SZ; -				dlen = _getshort((u_char*)cp); -				cp += INT16SZ; -				cp += dlen; +	if (_res.pfcode && !sflag) +		return; + +	opcode = ns_msg_getflag(*handle, ns_f_opcode); +	rrnum = 0; +	for (;;) { +		if (ns_parserr(handle, section, rrnum, &rr)) { +			if (errno != ENODEV) +				fprintf(file, ";; ns_parserr: %s\n", +					strerror(errno)); +			else if (rrnum > 0 && sflag != 0 && +				 (_res.pfcode & RES_PRF_HEAD1)) +				putc('\n', file); +			return; +		} +		if (rrnum == 0 && sflag != 0 && (_res.pfcode & RES_PRF_HEAD1)) +			fprintf(file, ";; %s SECTION:\n", +				p_section(section, opcode)); +		if (section == ns_s_qd) +			fprintf(file, ";;\t%s, type = %s, class = %s\n", +				ns_rr_name(rr), +				p_type(ns_rr_type(rr)), +				p_class(ns_rr_class(rr))); +		else { +			n = ns_sprintrr(handle, &rr, NULL, NULL, +					buf, sizeof buf); +			if (n < 0) { +				fprintf(file, ";; ns_sprintrr: %s\n", +					strerror(errno)); +				return;  			} -			if ((cp - msg) > len) -				return (NULL); +			fputs(buf, file); +			fputc('\n', file);  		} -		if ((!_res.pfcode) || -		    ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) -			putc('\n', file); +		rrnum++;  	} -	return (cp);  }  void -__p_query(msg) -	const u_char *msg; -{ -	__fp_query(msg, stdout); +p_query(const u_char *msg) { +	fp_query(msg, stdout);  } -/* - * Print the current options. - * This is intended to be primarily a debugging routine. - */  void -__fp_resstat(statp, file) -	struct __res_state *statp; -	FILE *file; -{ -	register u_long mask; - -	fprintf(file, ";; res options:"); -	if (!statp) -		statp = &_res; -	for (mask = 1;  mask != 0;  mask <<= 1) -		if (statp->options & mask) -			fprintf(file, " %s", p_option(mask)); -	putc('\n', file); +fp_query(const u_char *msg, FILE *file) { +	fp_nquery(msg, PACKETSZ, file);  }  /* @@ -257,147 +202,82 @@ __fp_resstat(statp, file)   * This is intended to be primarily a debugging routine.   */  void -__fp_nquery(msg, len, file) -	const u_char *msg; -	int len; -	FILE *file; -{ -	register const u_char *cp, *endMark; -	register const HEADER *hp; -	register int n; +fp_nquery(const u_char *msg, int len, FILE *file) { +	ns_msg handle; +	int n, qdcount, ancount, nscount, arcount; +	u_int opcode, rcode, id;  	if ((_res.options & RES_INIT) == 0 && res_init() == -1)  		return; -#define TruncTest(x) if (x > endMark) goto trunc -#define	ErrorTest(x) if (x == NULL) goto error +	if (ns_initparse(msg, len, &handle) < 0) { +		fprintf(file, ";; ns_initparse: %s\n", strerror(errno)); +		return; +	} +	opcode = ns_msg_getflag(handle, ns_f_opcode); +	rcode = ns_msg_getflag(handle, ns_f_rcode); +	id = ns_msg_id(handle); +	qdcount = ns_msg_count(handle, ns_s_qd); +	ancount = ns_msg_count(handle, ns_s_an); +	nscount = ns_msg_count(handle, ns_s_ns); +	arcount = ns_msg_count(handle, ns_s_ar);  	/*  	 * Print header fields.  	 */ -	hp = (HEADER *)msg; -	cp = msg + HFIXEDSZ; -	endMark = msg + len; -	if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) { -		fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d", -			_res_opcodes[hp->opcode], -			_res_resultcodes[hp->rcode], -			ntohs(hp->id)); -		putc('\n', file); -	} +	if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || rcode) +		fprintf(file, +			";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n", +			_res_opcodes[opcode], _res_resultcodes[rcode], id);  	if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX))  		putc(';', file);  	if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {  		fprintf(file, "; flags:"); -		if (hp->qr) +		if (ns_msg_getflag(handle, ns_f_qr))  			fprintf(file, " qr"); -		if (hp->aa) +		if (ns_msg_getflag(handle, ns_f_aa))  			fprintf(file, " aa"); -		if (hp->tc) +		if (ns_msg_getflag(handle, ns_f_tc))  			fprintf(file, " tc"); -		if (hp->rd) +		if (ns_msg_getflag(handle, ns_f_rd))  			fprintf(file, " rd"); -		if (hp->ra) +		if (ns_msg_getflag(handle, ns_f_ra))  			fprintf(file, " ra"); -		if (hp->unused) -			fprintf(file, " UNUSED-BIT-ON"); -		if (hp->ad) +		if (ns_msg_getflag(handle, ns_f_z)) +			fprintf(file, " ??"); +		if (ns_msg_getflag(handle, ns_f_ad))  			fprintf(file, " ad"); -		if (hp->cd) +		if (ns_msg_getflag(handle, ns_f_cd))  			fprintf(file, " cd");  	}  	if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) { -		fprintf(file, "; Ques: %d", ntohs(hp->qdcount)); -		fprintf(file, ", Ans: %d", ntohs(hp->ancount)); -		fprintf(file, ", Auth: %d", ntohs(hp->nscount)); -		fprintf(file, ", Addit: %d", ntohs(hp->arcount)); +		fprintf(file, "; %s: %d", +			p_section(ns_s_qd, opcode), qdcount); +		fprintf(file, ", %s: %d", +			p_section(ns_s_an, opcode), ancount); +		fprintf(file, ", %s: %d", +			p_section(ns_s_ns, opcode), nscount); +		fprintf(file, ", %s: %d", +			p_section(ns_s_ar, opcode), arcount);  	}  	if ((!_res.pfcode) || (_res.pfcode &   		(RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {  		putc('\n',file);  	}  	/* -	 * Print question records. +	 * Print the various sections.  	 */ -	if ((n = ntohs(hp->qdcount)) != 0) { -		if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) -			fprintf(file, ";; QUESTIONS:\n"); -		while (--n >= 0) { -			if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) -				fprintf(file, ";;\t"); -			TruncTest(cp); -			if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) -				cp = p_cdnname(cp, msg, len, file); -			else { -				int n; -				char name[MAXDNAME]; - -				if ((n = dn_expand(msg, msg+len, cp, name, -						sizeof name)) < 0) -					cp = NULL; -				else -					cp += n; -			} -			ErrorTest(cp); -			TruncTest(cp); -			if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) -				fprintf(file, ", type = %s", -					__p_type(_getshort((u_char*)cp))); -			cp += INT16SZ; -			TruncTest(cp); -			if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) -				fprintf(file, ", class = %s\n", -					__p_class(_getshort((u_char*)cp))); -			cp += INT16SZ; -			if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) -				putc('\n', file); -		} -	} -	/* -	 * Print authoritative answer records -	 */ -	TruncTest(cp); -	cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file, -		      ";; ANSWERS:\n"); -	ErrorTest(cp); - -	/* -	 * print name server records -	 */ -	TruncTest(cp); -	cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file, -		      ";; AUTHORITY RECORDS:\n"); -	ErrorTest(cp); - -	TruncTest(cp); -	/* -	 * print additional records -	 */ -	cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file, -		      ";; ADDITIONAL RECORDS:\n"); -	ErrorTest(cp); -	return; - trunc: -	fprintf(file, "\n;; ...truncated\n"); -	return; - error: -	fprintf(file, "\n;; ...malformed\n"); -} - -void -__fp_query(msg, file) -	const u_char *msg; -	FILE *file; -{ -	fp_nquery(msg, PACKETSZ, file); +	do_section(&handle, ns_s_qd, RES_PRF_QUES, file); +	do_section(&handle, ns_s_an, RES_PRF_ANS, file); +	do_section(&handle, ns_s_ns, RES_PRF_AUTH, file); +	do_section(&handle, ns_s_ar, RES_PRF_ADD, file); +	if (qdcount == 0 && ancount == 0 && +	    nscount == 0 && arcount == 0) +		putc('\n', file);  }  const u_char * -__p_cdnname(cp, msg, len, file) -	const u_char *cp, *msg; -	int len; -	FILE *file; -{ +p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) {  	char name[MAXDNAME];  	int n; @@ -411,19 +291,15 @@ __p_cdnname(cp, msg, len, file)  }  const u_char * -__p_cdname(cp, msg, file) -	const u_char *cp, *msg; -	FILE *file; -{ +p_cdname(const u_char *cp, const u_char *msg, FILE *file) {  	return (p_cdnname(cp, msg, PACKETSZ, file));  } -  /* Return a fully-qualified domain name from a compressed name (with     length supplied).  */  const u_char * -__p_fqnname(cp, msg, msglen, name, namelen) +p_fqnname(cp, msg, msglen, name, namelen)  	const u_char *cp, *msg;  	int msglen;  	char *name; @@ -433,27 +309,24 @@ __p_fqnname(cp, msg, msglen, name, namelen)  	if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)  		return (NULL); -	newlen = strlen (name); -	if (newlen == 0 || name[newlen - 1] != '.') -		if (newlen+1 >= namelen)	/* Lack space for final dot */ +	newlen = strlen(name); +	if (newlen == 0 || name[newlen - 1] != '.') { +		if (newlen + 1 >= namelen)	/* Lack space for final dot */  			return (NULL);  		else  			strcpy(name + newlen, "."); +	}  	return (cp + n);  } -/* XXX:	the rest of these functions need to become length-limited, too. (vix) - */ +/* XXX:	the rest of these functions need to become length-limited, too. */  const u_char * -__p_fqname(cp, msg, file) -	const u_char *cp, *msg; -	FILE *file; -{ +p_fqname(const u_char *cp, const u_char *msg, FILE *file) {  	char name[MAXDNAME];  	const u_char *n; -	n = __p_fqnname(cp, msg, MAXCDNAME, name, sizeof name); +	n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);  	if (n == NULL)  		return (NULL);  	fputs(name, file); @@ -461,397 +334,6 @@ __p_fqname(cp, msg, file)  }  /* - * Print resource record fields in human readable form. - */ -const u_char * -__p_rr(cp, msg, file) -	const u_char *cp, *msg; -	FILE *file; -{ -	int type, class, dlen, n, c; -	struct in_addr inaddr; -	const u_char *cp1, *cp2; -	u_int32_t tmpttl, t; -	int lcnt; -	u_int16_t keyflags; -	char rrname[MAXDNAME];		/* The fqdn of this RR */ -	char base64_key[MAX_KEY_BASE64]; - -	if ((_res.options & RES_INIT) == 0 && res_init() == -1) { -		h_errno = NETDB_INTERNAL; -		return (NULL); -	} -	cp = __p_fqnname(cp, msg, MAXCDNAME, rrname, sizeof rrname); -	if (!cp) -		return (NULL);			/* compression error */ -	fputs(rrname, file); -	 -	type = _getshort((u_char*)cp); -	cp += INT16SZ; -	class = _getshort((u_char*)cp); -	cp += INT16SZ; -	tmpttl = _getlong((u_char*)cp); -	cp += INT32SZ; -	dlen = _getshort((u_char*)cp); -	cp += INT16SZ; -	cp1 = cp; -	if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID)) -		fprintf(file, "\t%lu", (u_long)tmpttl); -	if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS)) -		fprintf(file, "\t%s", __p_class(class)); -	fprintf(file, "\t%s", __p_type(type)); -	/* -	 * Print type specific data, if appropriate -	 */ -	switch (type) { -	case T_A: -		switch (class) { -		case C_IN: -		case C_HS: -			bcopy(cp, (char *)&inaddr, INADDRSZ); -			if (dlen == 4) { -				fprintf(file, "\t%s", inet_ntoa(inaddr)); -				cp += dlen; -			} else if (dlen == 7) { -				char *address; -				u_char protocol; -				u_short port; - -				address = inet_ntoa(inaddr); -				cp += INADDRSZ; -				protocol = *(u_char*)cp; -				cp += sizeof (u_char); -				port = _getshort((u_char*)cp); -				cp += INT16SZ; -				fprintf(file, "\t%s\t; proto %d, port %d", -					address, protocol, port); -			} -			break; -		default: -			cp += dlen; -		} -		break; -	case T_CNAME: -	case T_MB: -	case T_MG: -	case T_MR: -	case T_NS: -	case T_PTR: -		putc('\t', file); -		if ((cp = p_fqname(cp, msg, file)) == NULL) -			return (NULL); -		break; - -	case T_HINFO: -	case T_ISDN: -		cp2 = cp + dlen; -		(void) fputs("\t\"", file); -		if ((n = (unsigned char) *cp++) != 0) { -			for (c = n; c > 0 && cp < cp2; c--) { -				if (strchr("\n\"\\", *cp)) -					(void) putc('\\', file); -				(void) putc(*cp++, file); -			} -		} -		putc('"', file); -		if (cp < cp2 && (n = (unsigned char) *cp++) != 0) { -			(void) fputs ("\t\"", file); -			for (c = n; c > 0 && cp < cp2; c--) { -				if (strchr("\n\"\\", *cp)) -					(void) putc('\\', file); -				(void) putc(*cp++, file); -			} -			putc('"', file); -		} else if (type == T_HINFO) { -			(void) fputs("\"?\"", file); -			fprintf(file, "\n;; *** Warning *** OS-type missing"); -		} -		break; - -	case T_SOA: -		putc('\t', file); -		if ((cp = p_fqname(cp, msg, file)) == NULL) -			return (NULL); -		putc(' ', file); -		if ((cp = p_fqname(cp, msg, file)) == NULL) -			return (NULL); -		fputs(" (\n", file); -		t = _getlong((u_char*)cp);  cp += INT32SZ; -		fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t); -		t = _getlong((u_char*)cp);  cp += INT32SZ; -		fprintf(file, "\t\t\t%lu\t; refresh (%s)\n", -			(u_long)t, __p_time(t)); -		t = _getlong((u_char*)cp);  cp += INT32SZ; -		fprintf(file, "\t\t\t%lu\t; retry (%s)\n", -			(u_long)t, __p_time(t)); -		t = _getlong((u_char*)cp);  cp += INT32SZ; -		fprintf(file, "\t\t\t%lu\t; expire (%s)\n", -			(u_long)t, __p_time(t)); -		t = _getlong((u_char*)cp);  cp += INT32SZ; -		fprintf(file, "\t\t\t%lu )\t; minimum (%s)", -			(u_long)t, __p_time(t)); -		break; - -	case T_MX: -	case T_AFSDB: -	case T_RT: -		fprintf(file, "\t%d ", _getshort((u_char*)cp)); -		cp += INT16SZ; -		if ((cp = p_fqname(cp, msg, file)) == NULL) -			return (NULL); -		break; - -	case T_PX: -		fprintf(file, "\t%d ", _getshort((u_char*)cp)); -		cp += INT16SZ; -		if ((cp = p_fqname(cp, msg, file)) == NULL) -			return (NULL); -		putc(' ', file); -		if ((cp = p_fqname(cp, msg, file)) == NULL) -			return (NULL); -		break; - -	case T_X25: -		cp2 = cp + dlen; -		(void) fputs("\t\"", file); -		if ((n = (unsigned char) *cp++) != 0) { -			for (c = n; c > 0 && cp < cp2; c--) { -				if (strchr("\n\"\\", *cp)) -					(void) putc('\\', file); -				(void) putc(*cp++, file); -			} -		} -		putc('"', file); -		break; - -	case T_TXT: -		(void) putc('\t', file); -		cp2 = cp1 + dlen; -		while (cp < cp2) { -			putc('"', file); -			if ((n = (unsigned char) *cp++) != '\0') { -				for (c = n; c > 0 && cp < cp2; c--) { -					if (strchr("\n\"\\", *cp)) -						(void) putc('\\', file); -					(void) putc(*cp++, file); -				} -			} -			putc('"', file); -			if (cp < cp2) -				putc(' ', file); -		} -		break; - -	case T_NSAP: -		(void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL)); -		cp += dlen; -		break; - -	case T_AAAA: { -		char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; - -		fprintf(file, "\t%s", inet_ntop(AF_INET6, cp, t, sizeof t)); -		cp += dlen; -		break; -	    } - -	case T_LOC: { -		char t[255]; - -		fprintf(file, "\t%s", loc_ntoa(cp, t)); -		cp += dlen; -		break; -	    } - -	case T_NAPTR: { -		u_int order, preference; - -		order = _getshort(cp);  cp += INT16SZ; -		preference   = _getshort(cp);  cp += INT16SZ; -		fprintf(file, "\t%u %u ",order, preference); -		/* Flags */ -		n = *cp++; -		fprintf(file,"\"%.*s\" ", (int)n, cp); -		cp += n; -		/* Service */ -		n = *cp++; -		fprintf(file,"\"%.*s\" ", (int)n, cp); -		cp += n; -		/* Regexp */ -		n = *cp++; -		fprintf(file,"\"%.*s\" ", (int)n, cp); -		cp += n; -		if ((cp = p_fqname(cp, msg, file)) == NULL) -			return (NULL); -		break; -	    } - -	case T_SRV: { -		u_int priority, weight, port; - -		priority = _getshort(cp);  cp += INT16SZ; -		weight   = _getshort(cp);  cp += INT16SZ; -		port     = _getshort(cp);  cp += INT16SZ; -		fprintf(file, "\t%u %u %u ", priority, weight, port); -		if ((cp = p_fqname(cp, msg, file)) == NULL) -			return (NULL); -		break; -	    } - -	case T_MINFO: -	case T_RP: -		putc('\t', file); -		if ((cp = p_fqname(cp, msg, file)) == NULL) -			return (NULL); -		putc(' ', file); -		if ((cp = p_fqname(cp, msg, file)) == NULL) -			return (NULL); -		break; - -	case T_UINFO: -		putc('\t', file); -		fputs((char *)cp, file); -		cp += dlen; -		break; - -	case T_UID: -	case T_GID: -		if (dlen == 4) { -			fprintf(file, "\t%u", _getlong((u_char*)cp)); -			cp += INT32SZ; -		} -		break; - -	case T_WKS: -		if (dlen < INT32SZ + 1) -			break; -		bcopy(cp, (char *)&inaddr, INADDRSZ); -		cp += INT32SZ; -		fprintf(file, "\t%s %s ( ", -			inet_ntoa(inaddr), -			deproto((int) *cp)); -		cp += sizeof (u_char); -		n = 0; -		lcnt = 0; -		while (cp < cp1 + dlen) { -			c = *cp++; -			do { -				if (c & 0200) { -					if (lcnt == 0) { -						fputs("\n\t\t\t", file); -						lcnt = 5; -					} -					fputs(dewks(n), file); -					putc(' ', file); -					lcnt--; -				} -				c <<= 1; -			} while (++n & 07); -		} -		putc(')', file); -		break; - -	case T_KEY: -		putc('\t', file); -		keyflags = _getshort(cp); -		cp += 2; -		fprintf(file,"0x%04x", keyflags );	/* flags */ -		fprintf(file," %u", *cp++);	/* protocol */ -		fprintf(file," %u (", *cp++);	/* algorithm */ - -		n = b64_ntop(cp, (cp1 + dlen) - cp, -			     base64_key, sizeof base64_key); -		for (c = 0; c < n; ++c) { -			if (0 == (c & 0x3F)) -				fprintf(file, "\n\t"); -			putc(base64_key[c], file);  /* public key data */ -		} - -		fprintf(file, " )"); -		if (n < 0) -			fprintf(file, "\t; BAD BASE64"); -		fflush(file); -		cp = cp1 + dlen; -		break; - -	case T_SIG: -	        type = _getshort((u_char*)cp); -		cp += INT16SZ; -		fprintf(file, " %s", p_type(type)); -		fprintf(file, "\t%d", *cp++);	/* algorithm */ -		/* Check label value and print error if wrong. */ -		n = *cp++; -		c = dn_count_labels (rrname); -		if (n != c) -			fprintf(file, "\t; LABELS WRONG (%d should be %d)\n\t", -				n, c); -		/* orig ttl */ -		n = _getlong((u_char*)cp); -		if (n != tmpttl) -			fprintf(file, " %u", n); -		cp += INT32SZ; -		/* sig expire */ -		fprintf(file, " (\n\t%s", -				     __p_secstodate(_getlong((u_char*)cp))); -		cp += INT32SZ; -		/* time signed */ -		fprintf(file, " %s", __p_secstodate(_getlong((u_char*)cp))); -		cp += INT32SZ; -		/* sig footprint */ -		fprintf(file," %u ", _getshort((u_char*)cp)); -		cp += INT16SZ; -		/* signer's name */ -		cp = p_fqname(cp, msg, file); -		n = b64_ntop(cp, (cp1 + dlen) - cp, -			     base64_key, sizeof base64_key); -		for (c = 0; c < n; c++) { -			if (0 == (c & 0x3F)) -				fprintf (file, "\n\t"); -			putc(base64_key[c], file);		/* signature */ -		} -		/* Clean up... */ -		fprintf(file, " )"); -		if (n < 0) -			fprintf(file, "\t; BAD BASE64"); -		fflush(file); -		cp = cp1+dlen; -		break; - -#ifdef ALLOW_T_UNSPEC -	case T_UNSPEC: -		{ -			int NumBytes = 8; -			u_char *DataPtr; -			int i; - -			if (dlen < NumBytes) NumBytes = dlen; -			fprintf(file, "\tFirst %d bytes of hex data:", -				NumBytes); -			for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++) -				fprintf(file, " %x", *DataPtr); -			cp += dlen; -		} -		break; -#endif /* ALLOW_T_UNSPEC */ - -	default: -		fprintf(file, "\t?%d?", type); -		cp += dlen; -	} -#if 0 -	fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl)); -#else -	putc('\n', file); -#endif -	if (cp - cp1 != dlen) { -		fprintf(file, ";; packet size error (found %d, dlen was %d)\n", -			cp - cp1, dlen); -		cp = NULL; -	} -	return (cp); -} - -/*   * Names of RR classes and qclasses.  Classes and qclasses are the same, except   * that C_ANY is a qclass but not a class.  (You can ask for records of class   * C_ANY, but you can't have any records of that class in the database.) @@ -862,10 +344,30 @@ const struct res_sym __p_class_syms[] = {  	{C_HS,		"HS"},  	{C_HS,		"HESIOD"},  	{C_ANY,		"ANY"}, +	{C_NONE,	"NONE"},  	{C_IN, 		(char *)0}  };  /* + * Names of message sections. + */ +const struct res_sym __p_default_section_syms[] = { +	{ns_s_qd,	"QUERY"}, +	{ns_s_an,	"ANSWER"}, +	{ns_s_ns,	"AUTHORITY"}, +	{ns_s_ar,	"ADDITIONAL"}, +	{0,             (char *)0} +}; + +const struct res_sym __p_update_section_syms[] = { +	{S_ZONE,	"ZONE"}, +	{S_PREREQ,	"PREREQUISITE"}, +	{S_UPDATE,	"UPDATE"}, +	{S_ADDT,	"ADDITIONAL"}, +	{0,             (char *)0} +}; + +/*   * Names of RR types and qtypes.  Types and qtypes are the same, except   * that T_ANY is a qtype but not a type.  (You can ask for records of type   * T_ANY, but you can't have any records of that type in the database.) @@ -909,24 +411,14 @@ const struct res_sym __p_type_syms[] = {  	{T_AXFR,	"AXFR",		"zone transfer"},  	{T_MAILB,	"MAILB",	"mailbox-related data (deprecated)"},  	{T_MAILA,	"MAILA",	"mail agent (deprecated)"}, -	{T_UINFO,	"UINFO",	"user information (nonstandard)"}, -	{T_UID,		"UID",		"user ID (nonstandard)"}, -	{T_GID,		"GID",		"group ID (nonstandard)"},  	{T_NAPTR,	"NAPTR",	"URN Naming Authority"}, -#ifdef ALLOW_T_UNSPEC -	{T_UNSPEC,	"UNSPEC",	"unspecified data (nonstandard)"}, -#endif /* ALLOW_T_UNSPEC */  	{T_ANY,		"ANY",		"\"any\""},  	{0, 		NULL,		NULL}  };  int -__sym_ston(syms, name, success) -	const struct res_sym *syms; -	char *name; -	int *success; -{ -	for (NULL; syms->name != 0; syms++) { +sym_ston(const struct res_sym *syms, const char *name, int *success) { +	for ((void)NULL; syms->name != 0; syms++) {  		if (strcasecmp (name, syms->name) == 0) {  			if (success)  				*success = 1; @@ -939,14 +431,10 @@ __sym_ston(syms, name, success)  }  const char * -__sym_ntos(syms, number, success) -	const struct res_sym *syms; -	int number; -	int *success; -{ +sym_ntos(const struct res_sym *syms, int number, int *success) {  	static char unname[20]; -	for (NULL; syms->name != 0; syms++) { +	for ((void)NULL; syms->name != 0; syms++) {  		if (number == syms->number) {  			if (success)  				*success = 1; @@ -954,22 +442,17 @@ __sym_ntos(syms, number, success)  		}  	} -	sprintf (unname, "%d", number); +	sprintf(unname, "%d", number);  	if (success)  		*success = 0;  	return (unname);  } -  const char * -__sym_ntop(syms, number, success) -	const struct res_sym *syms; -	int number; -	int *success; -{ +sym_ntop(const struct res_sym *syms, int number, int *success) {  	static char unname[20]; -	for (NULL; syms->name != 0; syms++) { +	for ((void)NULL; syms->name != 0; syms++) {  		if (number == syms->number) {  			if (success)  				*success = 1; @@ -983,32 +466,44 @@ __sym_ntop(syms, number, success)  }  /* - * Return a string for the type + * Return a string for the type.   */  const char * -__p_type(type) -	int type; -{ -	return (__sym_ntos (__p_type_syms, type, (int *)0)); +p_type(int type) { +	return (sym_ntos(__p_type_syms, type, (int *)0));  }  /* - * Return a mnemonic for class + * Return a string for the type.   */  const char * -__p_class(class) -	int class; -{ -	return (__sym_ntos (__p_class_syms, class, (int *)0)); +p_section(int section, int opcode) { +	const struct res_sym *symbols; + +	switch (opcode) { +	case ns_o_update: +		symbols = __p_update_section_syms; +		break; +	default: +		symbols = __p_default_section_syms; +		break; +	} +	return (sym_ntos(symbols, section, (int *)0)); +} + +/* + * Return a mnemonic for class. + */ +const char * +p_class(int class) { +	return (sym_ntos(__p_class_syms, class, (int *)0));  }  /*   * Return a mnemonic for an option   */  const char * -__p_option(option) -	u_long option; -{ +p_option(u_long option) {  	static char nbuf[40];  	switch (option) { @@ -1030,56 +525,18 @@ __p_option(option)  }  /* - * Return a mnemonic for a time to live + * Return a mnemonic for a time to live.   */  const char * -p_time(value) -	u_int32_t value; -{ +p_time(u_int32_t value) {  	static char nbuf[40]; -	int secs, mins, hours, days; -	register char *p; - -	if (value == 0) { -		strcpy(nbuf, "0 secs"); -		return (nbuf); -	} -	secs = value % 60; -	value /= 60; -	mins = value % 60; -	value /= 60; -	hours = value % 24; -	value /= 24; -	days = value; -	value = 0; - -#define	PLURALIZE(x)	x, (x == 1) ? "" : "s" -	p = nbuf; -	if (days) { -		(void)sprintf(p, "%d day%s", PLURALIZE(days)); -		while (*++p); -	} -	if (hours) { -		if (days) -			*p++ = ' '; -		(void)sprintf(p, "%d hour%s", PLURALIZE(hours)); -		while (*++p); -	} -	if (mins) { -		if (days || hours) -			*p++ = ' '; -		(void)sprintf(p, "%d min%s", PLURALIZE(mins)); -		while (*++p); -	} -	if (secs || ! (days || hours || mins)) { -		if (days || hours || mins) -			*p++ = ' '; -		(void)sprintf(p, "%d sec%s", PLURALIZE(secs)); -	} +	if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0) +		sprintf(nbuf, "%u", value);  	return (nbuf);  } +  /*   * routines to convert between on-the-wire RR format and zone file format.   * Does not contain conversion to/from decimal degrees; divide or multiply @@ -1112,47 +569,40 @@ static u_int8_t  precsize_aton(strptr)  	char **strptr;  { +	unsigned int mval = 0, cmval = 0;  	u_int8_t retval = 0;  	char *cp; -	int exponent = 0; -	int mantissa = 0; +	int exponent; +	int mantissa;  	cp = *strptr; -	while (isdigit(*cp)) { -		if (mantissa == 0) -			mantissa = *cp - '0'; -		else -			exponent++; -		cp++; -	} -	if (*cp == '.') { +	while (isdigit(*cp)) +		mval = mval * 10 + (*cp++ - '0'); + +	if (*cp == '.') {		/* centimeters */  		cp++;  		if (isdigit(*cp)) { -			if (mantissa == 0) -				mantissa = *cp - '0'; -			else -				exponent++; -			cp++; - +			cmval = (*cp++ - '0') * 10;  			if (isdigit(*cp)) { -				if (mantissa == 0) -					mantissa = *cp - '0'; -				else -					exponent++; -				cp++; +				cmval += (*cp++ - '0');  			} -			else -				exponent++;  		}  	} -	else -		exponent += 2; +	cmval = (mval * 100) + cmval; + +	for (exponent = 0; exponent < 9; exponent++) +		if (cmval < poweroften[exponent+1]) +			break; + +	mantissa = cmval / poweroften[exponent]; +	if (mantissa > 9) +		mantissa = 9; -	if (mantissa == 0) -		exponent = 0;  	retval = (mantissa << 4) | exponent; +  	*strptr = cp; +  	return (retval);  } @@ -1162,7 +612,7 @@ latlon2ul(latlonstrptr,which)  	char **latlonstrptr;  	int *which;  { -	register char *cp; +	char *cp;  	u_int32_t retval;  	int deg = 0, min = 0, secs = 0, secsfrac = 0; @@ -1373,14 +823,14 @@ loc_ntoa(binary, ascii)  	char *ascii;  {  	static char *error = "?"; -	register const u_char *cp = binary; +	const u_char *cp = binary;  	int latdeg, latmin, latsec, latsecfrac;  	int longdeg, longmin, longsec, longsecfrac;  	char northsouth, eastwest;  	int altmeters, altfrac, altsign; -	const int referencealt = 100000 * 100; +	const u_int32_t referencealt = 100000 * 100;  	int32_t latval, longval, altval;  	u_int32_t templ; @@ -1391,7 +841,7 @@ loc_ntoa(binary, ascii)  	versionval = *cp++;  	if (versionval) { -		sprintf(ascii, "; error: unknown LOC RR version"); +		(void) sprintf(ascii, "; error: unknown LOC RR version");  		return (ascii);  	} @@ -1472,14 +922,12 @@ loc_ntoa(binary, ascii)  /* Return the number of DNS hierarchy levels in the name. */  int -__dn_count_labels(name) -	char *name; -{ +dn_count_labels(const char *name) {  	int i, len, count;  	len = strlen(name); - -	for(i = 0, count = 0; i < len; i++) { +	for (i = 0, count = 0; i < len; i++) { +		/* XXX need to check for \. or use named's nlabels(). */  		if (name[i] == '.')  			count++;  	} @@ -1503,9 +951,7 @@ __dn_count_labels(name)   * SIG records are required to be printed like this, by the Secure DNS RFC.   */  char * -__p_secstodate (secs) -	unsigned long secs; -{ +p_secstodate (u_long secs) {  	static char output[15];		/* YYYYMMDDHHMMSS and null */  	time_t clock = secs;  	struct tm *time; diff --git a/lib/libc/net/res_init.c b/lib/libc/net/res_init.c index bf1228067fd9..b9eddaa47ca6 100644 --- a/lib/libc/net/res_init.c +++ b/lib/libc/net/res_init.c @@ -1,6 +1,4 @@  /* - * ++Copyright++ 1985, 1989, 1993 - * -   * Copyright (c) 1985, 1989, 1993   *    The Regents of the University of California.  All rights reserved.   *  @@ -31,7 +29,9 @@   * 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. - * - + */ + +/*   * Portions Copyright (c) 1993 by Digital Equipment Corporation.   *    * Permission to use, copy, modify, and distribute this software for any @@ -49,14 +49,29 @@   * 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. - * - - * --Copyright-- + */ + +/* + * Portions 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 sccsid[] = "@(#)res_init.c	8.1 (Berkeley) 6/7/93"; -static char orig_rcsid[] = "From: Id: res_init.c,v 8.8 1997/06/01 20:34:37 vixie Exp"; -static char rcsid[] = "$Id: res_init.c,v 1.13 1997/06/27 08:22:03 peter Exp $"; +static char orig_rcsid[] = "From: Id: res_init.c,v 8.7 1996/11/18 09:10:04 vixie Exp $"; +static char rcsid[] = "$Id: res_init.c,v 1.14 1997/09/01 01:19:20 brian Exp $";  #endif /* LIBC_SCCS and not lint */  #include <sys/types.h> @@ -65,16 +80,15 @@ static char rcsid[] = "$Id: res_init.c,v 1.13 1997/06/27 08:22:03 peter Exp $";  #include <sys/time.h>  #include <netinet/in.h>  #include <arpa/inet.h> - -#include "res_config.h"  #include <arpa/nameser.h> - -#include <stdio.h>  #include <ctype.h>  #include <resolv.h> -#include <unistd.h> +#include <stdio.h>  #include <stdlib.h>  #include <string.h> +#include <unistd.h> + +#include "res_config.h"  static void res_setoptions __P((char *, char *)); @@ -84,6 +98,10 @@ static const char sort_mask[] = "/&";  static u_int32_t net_mask __P((struct in_addr));  #endif +#if !defined(isascii) /* XXX - could be a function */ +# define isascii(c) (!(c & 0200)) +#endif +  /*   * Resolver state default settings.   */ @@ -94,6 +112,7 @@ struct __res_state _res  # endif  	; +  /*   * Set up default settings.  If the configuration file exist, the values   * there will have precedence.  Otherwise, the server address is set to @@ -376,7 +395,7 @@ res_init()  				printf(";;\t%s\n", *pp);  			printf(";;\t..END..\n");  		} -#endif /* DEBUG */ +#endif  #endif /* !RFC1535 */  	} diff --git a/lib/libc/net/res_mkquery.c b/lib/libc/net/res_mkquery.c index cfc9d3329d04..55c024e59556 100644 --- a/lib/libc/net/res_mkquery.c +++ b/lib/libc/net/res_mkquery.c @@ -1,6 +1,4 @@  /* - * ++Copyright++ 1985, 1993 - * -   * Copyright (c) 1985, 1993   *    The Regents of the University of California.  All rights reserved.   *  @@ -31,7 +29,9 @@   * 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. - * - + */ + +/*   * Portions Copyright (c) 1993 by Digital Equipment Corporation.   *    * Permission to use, copy, modify, and distribute this software for any @@ -49,28 +49,41 @@   * 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. - * - - * --Copyright-- + */ + +/* + * Portions 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 sccsid[] = "@(#)res_mkquery.c	8.1 (Berkeley) 6/4/93"; -static char orig_rcsid[] = "From: Id: res_mkquery.c,v 8.5 1996/08/27 08:33:28 vixie Exp "; -static char rcsid[] = "$Id$"; +static char orig_rcsid[] = "From: Id: res_mkquery.c,v 8.9 1997/04/24 22:22:36 vixie Exp $"; +static char rcsid[] = "$Id: res_mkquery.c,v 1.12 1997/02/22 15:00:33 peter Exp $";  #endif /* LIBC_SCCS and not lint */  #include <sys/types.h>  #include <sys/param.h>  #include <netinet/in.h> - -#include "res_config.h"  #include <arpa/nameser.h> - -#include <stdio.h>  #include <netdb.h>  #include <resolv.h> +#include <stdio.h>  #include <string.h> +#include "res_config.h"  /*   * Form all types of queries. @@ -106,7 +119,7 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)  	 */  	if ((buf == NULL) || (buflen < HFIXEDSZ))  		return (-1); -	bzero(buf, HFIXEDSZ); +	memset(buf, 0, HFIXEDSZ);  	hp = (HEADER *) buf;  	hp->id = htons(++_res.id);  	hp->opcode = op; @@ -173,7 +186,7 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)  		__putshort(datalen, cp);  		cp += INT16SZ;  		if (datalen) { -			bcopy(data, cp, datalen); +			memcpy(cp, data, datalen);  			cp += datalen;  		}  		hp->ancount = htons(1); diff --git a/lib/libc/net/res_mkupdate.c b/lib/libc/net/res_mkupdate.c new file mode 100644 index 000000000000..a9dcc8606fd4 --- /dev/null +++ b/lib/libc/net/res_mkupdate.c @@ -0,0 +1,414 @@ +/* + * 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. + */ + +/* + * Based on the Dynamic DNS reference implementation by Viraj Bais + * <viraj_bais@ccm.fm.intel.com> + */ + +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: res_mkupdate.c,v 1.11 1998/01/26 23:08:45 halley Exp $"; +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/param.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <limits.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> + +#include "res_config.h" + +static int getnum_str(u_char **, u_char *); +static int getword_str(char *, int, u_char **, u_char *); + +#define ShrinkBuffer(x)  if ((buflen -= x) < 0) return (-2); + +/* + * Form update packets. + * Returns the size of the resulting packet if no error + * On error, + *	returns -1 if error in reading a word/number in rdata + *		   portion for update packets + *		-2 if length of buffer passed is insufficient + *		-3 if zone section is not the first section in + *		   the linked list, or section order has a problem + *		-4 on a number overflow + *		-5 unknown operation or no records + */ +int +res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) { +	ns_updrec *rrecp_start = rrecp_in; +	HEADER *hp; +	u_char c, *cp, *cp1, *sp1, *sp2, *startp, *endp; +	int n, i, j, found, soanum, multiline; +	ns_updrec *rrecp, *tmprrecp, *recptr = NULL; +	struct in_addr ina; +        char buf2[MAXDNAME]; +	int section, numrrs = 0, counts[ns_s_max]; +	u_int16_t rtype, rclass; +	u_int32_t n1, rttl; +	u_char *dnptrs[20], **dpp, **lastdnptr; + +	if ((_res.options & RES_INIT) == 0 && res_init() == -1) { +		h_errno = NETDB_INTERNAL; +		return (-1); +	} + +	/* +	 * Initialize header fields. +	 */ +	if ((buf == NULL) || (buflen < HFIXEDSZ)) +		return (-1); +	memset(buf, 0, HFIXEDSZ); +	hp = (HEADER *) buf; +	hp->id = htons(++_res.id); +	hp->opcode = ns_o_update; +	hp->rcode = NOERROR; +	sp1 = buf + 2*INT16SZ;  /* save pointer to zocount */ +	cp = buf + HFIXEDSZ; +	buflen -= HFIXEDSZ; +	dpp = dnptrs; +	*dpp++ = buf; +	*dpp++ = NULL; +	lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; + +	if (rrecp_start == NULL) +		return (-5); +	else if (rrecp_start->r_section != S_ZONE) +		return (-3); + +	memset(counts, 0, sizeof counts); +	for (rrecp = rrecp_start; rrecp; rrecp = rrecp->r_grpnext) { +		numrrs++; +                section = rrecp->r_section; +		if (section < 0 || section >= ns_s_max) +			return (-1); +		counts[section]++; +		for (i = section + 1; i < ns_s_max; i++) +			if (counts[i]) +				return (-3); +		rtype = rrecp->r_type; +		rclass = rrecp->r_class; +		rttl = rrecp->r_ttl; +		/* overload class and type */ +		if (section == S_PREREQ) { +			rttl = 0; +			switch (rrecp->r_opcode) { +			case YXDOMAIN: +				rclass = C_ANY; +				rtype = T_ANY; +				rrecp->r_size = 0; +				break; +			case NXDOMAIN: +				rclass = C_NONE; +				rtype = T_ANY; +				rrecp->r_size = 0; +				break; +			case NXRRSET: +				rclass = C_NONE; +				rrecp->r_size = 0; +				break; +			case YXRRSET: +				if (rrecp->r_size == 0) +					rclass = C_ANY; +				break; +			default: +				fprintf(stderr, +					"res_mkupdate: incorrect opcode: %d\n", +					rrecp->r_opcode); +				fflush(stderr); +				return (-1); +			} +		} else if (section == S_UPDATE) { +			switch (rrecp->r_opcode) { +			case DELETE: +				rclass = rrecp->r_size == 0 ? C_ANY : C_NONE; +				break; +			case ADD: +				break; +			default: +				fprintf(stderr, +					"res_mkupdate: incorrect opcode: %d\n", +					rrecp->r_opcode); +				fflush(stderr); +				return (-1); +			} +		} + +		/* +		 * XXX	appending default domain to owner name is omitted, +		 *	fqdn must be provided +		 */ +		if ((n = dn_comp(rrecp->r_dname, cp, buflen, dnptrs, +				 lastdnptr)) < 0) +			return (-1); +		cp += n; +		ShrinkBuffer(n + 2*INT16SZ); +		PUTSHORT(rtype, cp); +		PUTSHORT(rclass, cp); +		if (section == S_ZONE) { +			if (numrrs != 1 || rrecp->r_type != T_SOA) +				return (-3); +			continue; +		} +		ShrinkBuffer(INT32SZ + INT16SZ); +		PUTLONG(rttl, cp); +		sp2 = cp;  /* save pointer to length byte */ +		cp += INT16SZ; +		if (rrecp->r_size == 0) { +			if (section == S_UPDATE && rclass != C_ANY) +				return (-1); +			else { +				PUTSHORT(0, sp2); +				continue; +			} +		} +		startp = rrecp->r_data; +		endp = startp + rrecp->r_size - 1; +		/* XXX this should be done centrally. */ +		switch (rrecp->r_type) { +		case T_A: +			if (!getword_str(buf2, sizeof buf2, &startp, endp)) +				return (-1); +			if (!inet_aton(buf2, &ina)) +				return (-1); +			n1 = ntohl(ina.s_addr); +			ShrinkBuffer(INT32SZ); +			PUTLONG(n1, cp); +			break; +		case T_CNAME: +		case T_MB: +		case T_MG: +		case T_MR: +		case T_NS: +		case T_PTR: +			if (!getword_str(buf2, sizeof buf2, &startp, endp)) +				return (-1); +			n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); +			if (n < 0) +				return (-1); +			cp += n; +			ShrinkBuffer(n); +			break; +		case T_MINFO: +		case T_SOA: +		case T_RP: +			for (i = 0; i < 2; i++) { +				if (!getword_str(buf2, sizeof buf2, &startp, +						 endp)) +				return (-1); +				n = dn_comp(buf2, cp, buflen, +					    dnptrs, lastdnptr); +				if (n < 0) +					return (-1); +				cp += n; +				ShrinkBuffer(n); +			} +			if (rrecp->r_type == T_SOA) { +				ShrinkBuffer(5 * INT32SZ); +				while (isspace(*startp) || !*startp) +					startp++; +				if (*startp == '(') { +					multiline = 1; +					startp++; +				} else +					multiline = 0; +				/* serial, refresh, retry, expire, minimum */ +				for (i = 0; i < 5; i++) { +					soanum = getnum_str(&startp, endp); +					if (soanum < 0) +						return (-1); +					PUTLONG(soanum, cp); +				} +				if (multiline) { +					while (isspace(*startp) || !*startp) +						startp++; +					if (*startp != ')') +						return (-1); +				} +			} +			break; +		case T_MX: +		case T_AFSDB: +		case T_RT: +			n = getnum_str(&startp, endp); +			if (n < 0) +				return (-1); +			PUTSHORT(n, cp); +			ShrinkBuffer(INT16SZ); +			if (!getword_str(buf2, sizeof buf2, &startp, endp)) +				return (-1); +			n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); +			if (n < 0) +				return (-1); +			cp += n; +			ShrinkBuffer(n); +			break; +		case T_PX: +			n = getnum_str(&startp, endp); +			if (n < 0) +				return (-1); +			PUTSHORT(n, cp); +			ShrinkBuffer(INT16SZ); +			for (i = 0; i < 2; i++) { +				if (!getword_str(buf2, sizeof buf2, &startp, +						 endp)) +					return (-1); +				n = dn_comp(buf2, cp, buflen, dnptrs, +					    lastdnptr); +				if (n < 0) +					return (-1); +				cp += n; +				ShrinkBuffer(n); +			} +			break; +		case T_WKS: +		case T_HINFO: +		case T_TXT: +		case T_X25: +		case T_ISDN: +		case T_NSAP: +		case T_LOC: +			/* XXX - more fine tuning needed here */ +			ShrinkBuffer(rrecp->r_size); +			memcpy(cp, rrecp->r_data, rrecp->r_size); +			cp += rrecp->r_size; +			break; +		default: +			return (-1); +		} /*switch*/ +		n = (u_int16_t)((cp - sp2) - INT16SZ); +		PUTSHORT(n, sp2); +	} /*for*/ +		 +	hp->qdcount = htons(counts[0]); +	hp->ancount = htons(counts[1]); +	hp->nscount = htons(counts[2]); +	hp->arcount = htons(counts[3]); +	return (cp - buf); +} + +/* + * Get a whitespace delimited word from a string (not file) + * into buf. modify the start pointer to point after the + * word in the string. + */ +static int +getword_str(char *buf, int size, u_char **startpp, u_char *endp) { +        char *cp; +        int c; +  +        for (cp = buf; *startpp <= endp; ) { +                c = **startpp; +                if (isspace(c) || c == '\0') { +                        if (cp != buf) /* trailing whitespace */ +                                break; +                        else { /* leading whitespace */ +                                (*startpp)++; +                                continue; +                        } +                } +                (*startpp)++; +                if (cp >= buf+size-1) +                        break; +                *cp++ = (u_char)c; +        } +        *cp = '\0'; +        return (cp != buf); +} + +/* + * Get a whitespace delimited number from a string (not file) into buf + * update the start pointer to point after the number in the string. + */ +static int +getnum_str(u_char **startpp, u_char *endp) { +        int c, n; +        int seendigit = 0; +        int seendecimal = 0; +        int m = 0; + +        for (n = 0; *startpp <= endp; ) { +                c = **startpp; +                if (isspace(c) || c == '\0') { +                        if (seendigit) /* trailing whitespace */ +                                break; +                        else { /* leading whitespace */ +                                (*startpp)++; +                                continue; +                        } +                } +                if (c == ';') { +                        while ((*startpp <= endp) && +			       ((c = **startpp) != '\n')) +					(*startpp)++; +                        if (seendigit) +                                break; +                        continue; +                } +                if (!isdigit(c)) { +                        if (c == ')' && seendigit) { +                                (*startpp)--; +                                break; +                        } +			return (-1); +                }         +                (*startpp)++; +                n = n * 10 + (c - '0'); +                seendigit = 1; +        } +        return (n + m); +} + +/* + * Allocate a resource record buffer & save rr info. + */ +ns_updrec * +res_mkupdrec(int section, const char *dname, +	     u_int class, u_int type, u_long ttl) { +	ns_updrec *rrecp = (ns_updrec *)calloc(1, sizeof(ns_updrec)); + +	if (!rrecp || !(rrecp->r_dname = strdup(dname))) +		return (NULL); + 	rrecp->r_class = class; +	rrecp->r_type = type; +	rrecp->r_ttl = ttl; +	rrecp->r_section = section; +	return (rrecp); +} + +/* + * Free a resource record buffer created by res_mkupdrec. + */ +void +res_freeupdrec(ns_updrec *rrecp) { +	/* Note: freeing r_dp is the caller's responsibility. */ +	if (rrecp->r_dname != NULL) +		free(rrecp->r_dname); +	free(rrecp); +} diff --git a/lib/libc/net/res_query.c b/lib/libc/net/res_query.c index 3716e63dd8f1..4de8a0e60fd4 100644 --- a/lib/libc/net/res_query.c +++ b/lib/libc/net/res_query.c @@ -1,6 +1,4 @@  /* - * ++Copyright++ 1988, 1993 - * -   * Copyright (c) 1988, 1993   *    The Regents of the University of California.  All rights reserved.   *  @@ -31,7 +29,9 @@   * 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. - * - + */ + +/*   * Portions Copyright (c) 1993 by Digital Equipment Corporation.   *    * Permission to use, copy, modify, and distribute this software for any @@ -49,41 +49,52 @@   * 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. - * - - * --Copyright-- + */ + +/* + * Portions 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 sccsid[] = "@(#)res_query.c	8.1 (Berkeley) 6/4/93"; -static char orig_rcsid = "From: Id: res_query.c,v 8.10 1997/06/01 20:34:37 vixie Exp"; -static char rcsid[] = "$Id: res_query.c,v 1.14 1997/06/27 08:22:03 peter Exp $"; +static char orig_rcsid = "From: Id: res_query.c,v 8.14 1997/06/09 17:47:05 halley Exp $"; +static char rcsid[] = "$Id: res_query.c,v 1.15 1997/09/01 01:19:21 brian Exp $";  #endif /* LIBC_SCCS and not lint */  #include <sys/types.h>  #include <sys/param.h>  #include <netinet/in.h>  #include <arpa/inet.h> - -#include "res_config.h"  #include <arpa/nameser.h> - -#include <stdio.h> -#include <netdb.h> -#include <resolv.h>  #include <ctype.h>  #include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h>  #include <stdlib.h>  #include <string.h> +#include "res_config.h" +  #if PACKETSZ > 1024  #define MAXPACKET	PACKETSZ  #else  #define MAXPACKET	1024  #endif -const char *hostalias __P((const char *)); -int h_errno; -  /*   * Formulate a normal query, send, and await answer.   * Returned answer is placed in supplied buffer "answer". @@ -102,7 +113,7 @@ res_query(name, class, type, answer, anslen)  	int anslen;		/* size of answer buffer */  {  	u_char buf[MAXPACKET]; -	register HEADER *hp = (HEADER *) answer; +	HEADER *hp = (HEADER *) answer;  	int n;  	hp->rcode = NOERROR;	/* default */ @@ -177,7 +188,7 @@ res_search(name, class, type, answer, anslen)  	u_char *answer;		/* buffer to put answer */  	int anslen;		/* size of answer */  { -	register const char *cp, * const *domain; +	const char *cp, * const *domain;  	HEADER *hp = (HEADER *) answer;  	u_int dots;  	int trailing_dot, ret, saved_herrno; @@ -196,10 +207,8 @@ res_search(name, class, type, answer, anslen)  	if (cp > name && *--cp == '.')  		trailing_dot++; -	/* -	 * if there aren't any dots, it could be a user-level alias -	 */ -	if (!dots && (cp = __hostalias(name)) != NULL) +	/* If there aren't any dots, it could be a user-level alias */ +	if (!dots && (cp = hostalias(name)) != NULL)  		return (res_query(cp, class, type, answer, anslen));  	/* @@ -279,7 +288,8 @@ res_search(name, class, type, answer, anslen)  		}  	} -	/* if we have not already tried the name "as is", do that now. +	/* +	 * If we have not already tried the name "as is", do that now.  	 * note that we do this regardless of how many dots were in the  	 * name or whether it ends with a dot unless NOTLDQUERY is set.  	 */ @@ -359,7 +369,7 @@ res_querydomain(name, domain, class, type, answer, anslen)  const char *  hostalias(name) -	register const char *name; +	const char *name;  {  	register char *cp1, *cp2;  	FILE *fp; @@ -369,8 +379,7 @@ hostalias(name)  	if (_res.options & RES_NOALIASES)  		return (NULL); -	/* XXX issetguid() would be better here, but we don't have that. */ -	if (getuid() != geteuid() || getgid() != getegid()) +	if (issetugid())  		return (NULL);  	file = getenv("HOSTALIASES");  	if (file == NULL || (fp = fopen(file, "r")) == NULL) diff --git a/lib/libc/net/res_send.c b/lib/libc/net/res_send.c index a29f43a6f508..45c966128131 100644 --- a/lib/libc/net/res_send.c +++ b/lib/libc/net/res_send.c @@ -1,6 +1,4 @@  /* - * ++Copyright++ 1985, 1989, 1993 - * -   * Copyright (c) 1985, 1989, 1993   *    The Regents of the University of California.  All rights reserved.   *  @@ -31,7 +29,9 @@   * 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. - * - + */ + +/*   * Portions Copyright (c) 1993 by Digital Equipment Corporation.   *    * Permission to use, copy, modify, and distribute this software for any @@ -49,14 +49,29 @@   * 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. - * - - * --Copyright-- + */ + +/* + * Portions 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 sccsid[] = "@(#)res_send.c	8.1 (Berkeley) 6/4/93"; -static char orig_rcsid[] = "From: Id: res_send.c,v 8.14 1998/04/07 04:59:46 vixie Exp $"; -static char rcsid[] = "$Id: res_send.c,v 1.21 1998/05/02 13:11:02 peter Exp $"; +static char orig_rcsid[] = "From: Id: res_send.c,v 8.20 1998/04/06 23:27:51 halley Exp $"; +static char rcsid[] = "$Id: res_send.c,v 1.22 1998/05/02 15:51:54 peter Exp $";  #endif /* LIBC_SCCS and not lint */  /* @@ -68,27 +83,31 @@ static char rcsid[] = "$Id: res_send.c,v 1.21 1998/05/02 13:11:02 peter Exp $";  #include <sys/time.h>  #include <sys/socket.h>  #include <sys/uio.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include "res_config.h" +#include <netinet/in.h>  #include <arpa/nameser.h> +#include <arpa/inet.h> -#include <stdio.h> -#include <netdb.h>  #include <errno.h> +#include <netdb.h>  #include <resolv.h> +#include <stdio.h>  #include <stdlib.h>  #include <string.h>  #include <unistd.h>  #include <poll.h> +#include "res_config.h" +  static int use_poll = 1;	/* adapt to poll() syscall availability */  				/* 0 = not present, 1 = try it, 2 = exists */ -static int s = -1;	/* socket used for communications */ +static int s = -1;		/* socket used for communications */  static int connected = 0;	/* is the socket connected */ -static int vc = 0;	/* is the socket a virtual ciruit? */ +static int vc = 0;		/* is the socket a virtual circuit? */ +static res_send_qhook Qhook = NULL; +static res_send_rhook Rhook = NULL; +  #define CAN_RECONNECT 1 @@ -137,9 +156,6 @@ static int vc = 0;	/* is the socket a virtual ciruit? */      }  #endif -static res_send_qhook Qhook = NULL; -static res_send_rhook Rhook = NULL; -  void  res_send_setqhook(hook)  	res_send_qhook hook; @@ -170,12 +186,12 @@ res_isourserver(inp)  	const struct sockaddr_in *inp;  {  	struct sockaddr_in ina; -	register int ns, ret; +	int ns, ret;  	ina = *inp;  	ret = 0;  	for (ns = 0;  ns < _res.nscount;  ns++) { -		register const struct sockaddr_in *srv = &_res.nsaddr_list[ns]; +		const struct sockaddr_in *srv = &_res.nsaddr_list[ns];  		if (srv->sin_family == ina.sin_family &&  		    srv->sin_port == ina.sin_port && @@ -192,7 +208,7 @@ res_isourserver(inp)   * res_nameinquery(name, type, class, buf, eom)   *	look for (name,type,class) in the query section of packet (buf,eom)   * requires: - *	buf + HFIXESDZ <= eom + *	buf + HFIXEDSZ <= eom   * returns:   *	-1 : format error   *	0  : not found @@ -203,15 +219,15 @@ res_isourserver(inp)  int  res_nameinquery(name, type, class, buf, eom)  	const char *name; -	register int type, class; +	int type, class;  	const u_char *buf, *eom;  { -	register const u_char *cp = buf + HFIXEDSZ; +	const u_char *cp = buf + HFIXEDSZ;  	int qdcount = ntohs(((HEADER*)buf)->qdcount);  	while (qdcount-- > 0) {  		char tname[MAXDNAME+1]; -		register int n, ttype, tclass; +		int n, ttype, tclass;  		n = dn_expand(buf, eom, cp, tname, sizeof tname);  		if (n < 0) @@ -219,8 +235,8 @@ res_nameinquery(name, type, class, buf, eom)  		cp += n;  		if (cp + 2 * INT16SZ > eom)  			return (-1); -		ttype = _getshort(cp); cp += INT16SZ; -		tclass = _getshort(cp); cp += INT16SZ; +		ttype = ns_get16(cp); cp += INT16SZ; +		tclass = ns_get16(cp); cp += INT16SZ;  		if (ttype == type &&  		    tclass == class &&  		    strcasecmp(tname, name) == 0) @@ -245,17 +261,25 @@ res_queriesmatch(buf1, eom1, buf2, eom2)  	const u_char *buf1, *eom1;  	const u_char *buf2, *eom2;  { -	register const u_char *cp = buf1 + HFIXEDSZ; +	const u_char *cp = buf1 + HFIXEDSZ;  	int qdcount = ntohs(((HEADER*)buf1)->qdcount);  	if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)  		return (-1); +	/* +	 * Only header section present in replies to +	 * dynamic update packets. +	 */ +	if ( (((HEADER *)buf1)->opcode == ns_o_update) && +	     (((HEADER *)buf2)->opcode == ns_o_update) ) +		return (1); +  	if (qdcount != ntohs(((HEADER*)buf2)->qdcount))  		return (0);  	while (qdcount-- > 0) {  		char tname[MAXDNAME+1]; -		register int n, ttype, tclass; +		int n, ttype, tclass;  		n = dn_expand(buf1, eom1, cp, tname, sizeof tname);  		if (n < 0) @@ -263,8 +287,8 @@ res_queriesmatch(buf1, eom1, buf2, eom2)  		cp += n;  		if (cp + 2 * INT16SZ > eom1)  			return (-1); -		ttype = _getshort(cp);	cp += INT16SZ; -		tclass = _getshort(cp); cp += INT16SZ; +		ttype = ns_get16(cp);	cp += INT16SZ; +		tclass = ns_get16(cp); cp += INT16SZ;  		if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))  			return (0);  	} @@ -280,9 +304,8 @@ res_send(buf, buflen, ans, anssiz)  {  	HEADER *hp = (HEADER *) buf;  	HEADER *anhp = (HEADER *) ans; -	int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns; -	register int n; -	u_int badns;	/* XXX NSMAX can't exceed #/bits in this var */ +	int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns, n; +	u_int badns;	/* XXX NSMAX can't exceed #/bits in this variable */  	if ((_res.options & RES_INIT) == 0 && res_init() == -1) {  		/* errno should have been set by res_init() in this case. */ @@ -358,7 +381,7 @@ res_send(buf, buflen, ans, anssiz)  			 */  			try = _res.retry;  			truncated = 0; -			if ((s < 0) || (!vc)) { +			if (s < 0 || !vc || hp->opcode == ns_o_update) {  				if (s >= 0)  					res_close(); @@ -370,7 +393,7 @@ res_send(buf, buflen, ans, anssiz)  				}  				errno = 0;  				if (connect(s, (struct sockaddr *)nsap, -					    sizeof(struct sockaddr)) < 0) { +					    sizeof *nsap) < 0) {  					terrno = errno;  					Aerror(stderr, "connect/vc",  					       errno, *nsap); @@ -427,7 +450,7 @@ read_len:  				res_close();  				goto next_ns;  			} -			resplen = _getshort(ans); +			resplen = ns_get16(ans);  			if (resplen > anssiz) {  				Dprint(_res.options & RES_DEBUG,  				       (stdout, ";; response truncated\n") @@ -509,7 +532,7 @@ read_len:  					res_close();  				s = socket(PF_INET, SOCK_DGRAM, 0);  				if (s < 0) { -#if !CAN_RECONNECT +#ifndef CAN_RECONNECT   bad_dg_sock:  #endif  					terrno = errno; @@ -518,6 +541,7 @@ read_len:  				}  				connected = 0;  			} +#ifndef CANNOT_CONNECT_DGRAM  			/*  			 * On a 4.3BSD+ machine (client and server,  			 * actually), sending to a nameserver datagram @@ -540,7 +564,7 @@ read_len:  				 */  				if (!connected) {  					if (connect(s, (struct sockaddr *)nsap, -						    sizeof(struct sockaddr) +						    sizeof *nsap  						    ) < 0) {  						Aerror(stderr,  						       "connect(dg)", @@ -563,7 +587,7 @@ read_len:  				 * for responses from more than one server.  				 */  				if (connected) { -#if CAN_RECONNECT +#ifdef CAN_RECONNECT  					struct sockaddr_in no_addr;  					no_addr.sin_family = AF_INET; @@ -572,7 +596,7 @@ read_len:  					(void) connect(s,  						       (struct sockaddr *)  						        &no_addr, -						       sizeof(no_addr)); +						       sizeof no_addr);  #else  					int s1 = socket(PF_INET, SOCK_DGRAM,0);  					if (s1 < 0) @@ -581,20 +605,23 @@ read_len:  					(void) close(s1);  					Dprint(_res.options & RES_DEBUG,  						(stdout, ";; new DG socket\n")) -#endif +#endif /* CAN_RECONNECT */  					connected = 0;  					errno = 0;  				} +#endif /* !CANNOT_CONNECT_DGRAM */  				if (sendto(s, (char*)buf, buflen, 0,  					   (struct sockaddr *)nsap, -					   sizeof(struct sockaddr)) +					   sizeof *nsap)  				    != buflen) {  					Aerror(stderr, "sendto", errno, *nsap);  					badns |= (1 << ns);  					res_close();  					goto next_ns;  				} +#ifndef CANNOT_CONNECT_DGRAM  			} +#endif /* !CANNOT_CONNECT_DGRAM */  			/*  			 * Wait for reply @@ -723,7 +750,7 @@ read_len:  					ans, (resplen>anssiz)?anssiz:resplen);  				goto wait;  			} -#if CHECK_SRVR_ADDR +#ifdef CHECK_SRVR_ADDR  			if (!(_res.options & RES_INSECURE1) &&  			    !res_isourserver(&from)) {  				/* @@ -830,12 +857,12 @@ read_len:  	   } /*foreach ns*/  	} /*foreach retry*/  	res_close(); -	if (!v_circuit) +	if (!v_circuit) {  		if (!gotsomewhere)  			errno = ECONNREFUSED;	/* no nameservers found */  		else  			errno = ETIMEDOUT;	/* no answer obtained */ -	else +	} else  		errno = terrno;  	return (-1);  } diff --git a/lib/libc/net/res_stubs.c b/lib/libc/net/res_stubs.c index e156608333e9..056bc6c9438e 100644 --- a/lib/libc/net/res_stubs.c +++ b/lib/libc/net/res_stubs.c @@ -23,7 +23,7 @@   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF   * SUCH DAMAGE.   * - * $Id: res_stubs.c,v 1.5 1997/02/22 15:00:36 peter Exp $ + * $Id: res_stubs.c,v 1.6 1997/06/27 08:35:13 peter Exp $   */  /* @@ -41,6 +41,21 @@  #include <sys/types.h>  #include <sys/cdefs.h> +__weak_reference(__inet_addr, inet_addr); +__weak_reference(__inet_aton, inet_aton); +__weak_reference(__inet_lnaof, inet_lnaof); +__weak_reference(__inet_makeaddr, inet_makeaddr); +__weak_reference(__inet_neta, inet_neta); +__weak_reference(__inet_netof, inet_netof); +__weak_reference(__inet_network, inet_network); +__weak_reference(__inet_net_ntop, inet_net_ntop); +__weak_reference(__inet_net_pton, inet_net_pton); +__weak_reference(__inet_ntoa, inet_ntoa); +__weak_reference(__inet_pton, inet_pton); +__weak_reference(__inet_ntop, inet_ntop); +__weak_reference(__inet_nsap_addr, inet_nsap_addr); +__weak_reference(__inet_nsap_ntoa, inet_nsap_ntoa); +  __weak_reference(__sym_ston, sym_ston);  __weak_reference(__sym_ntos, sym_ntos);  __weak_reference(__sym_ntop, sym_ntop); @@ -51,7 +66,6 @@ __weak_reference(__p_secstodate, p_secstodate);  __weak_reference(__dn_count_labels, dn_count_labels);  __weak_reference(__dn_comp, dn_comp);  __weak_reference(__res_close, _res_close); -#ifdef BIND_RES_POSIX3  __weak_reference(__dn_expand, dn_expand);  __weak_reference(__res_init, res_init);  __weak_reference(__res_query, res_query); @@ -59,6 +73,3 @@ __weak_reference(__res_search, res_search);  __weak_reference(__res_querydomain, res_querydomain);  __weak_reference(__res_mkquery, res_mkquery);  __weak_reference(__res_send, res_send); -#else -__weak_reference(res_send, __res_send); -#endif diff --git a/lib/libc/net/res_update.c b/lib/libc/net/res_update.c new file mode 100644 index 000000000000..c76d22e72fe1 --- /dev/null +++ b/lib/libc/net/res_update.c @@ -0,0 +1,516 @@ +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: res_update.c,v 1.14 1998/03/10 22:04:48 halley Exp $"; +#endif /* not lint */ + +/* + * 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. + */ + +/* + * Based on the Dynamic DNS reference implementation by Viraj Bais + * <viraj_bais@ccm.fm.intel.com> + */ + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> +#include <errno.h> +#include <limits.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * Separate a linked list of records into groups so that all records + * in a group will belong to a single zone on the nameserver. + * Create a dynamic update packet for each zone and send it to the + * nameservers for that zone, and await answer. + * Abort if error occurs in updating any zone. + * Return the number of zones updated on success, < 0 on error. + * + * On error, caller must deal with the unsynchronized zones + * eg. an A record might have been successfully added to the forward + * zone but the corresponding PTR record would be missing if error + * was encountered while updating the reverse zone. + */ + +#define NSMAX 16 + +struct ns1 { +	char nsname[MAXDNAME]; +	struct in_addr nsaddr1; +}; + +struct zonegrp { +	char 		z_origin[MAXDNAME]; +	int16_t		z_class; +	char		z_soardata[MAXDNAME + 5 * INT32SZ]; +	struct ns1 	z_ns[NSMAX]; +	int		z_nscount; +	ns_updrec *	z_rr; +	struct zonegrp *z_next; +}; + + +int +res_update(ns_updrec *rrecp_in) { +	ns_updrec *rrecp, *tmprrecp; +	u_char buf[PACKETSZ], answer[PACKETSZ], packet[2*PACKETSZ]; +	char name[MAXDNAME], zname[MAXDNAME], primary[MAXDNAME], +	     mailaddr[MAXDNAME]; +	u_char soardata[2*MAXCDNAME+5*INT32SZ]; +	char *dname, *svdname, *cp1, *target; +	u_char *cp, *eom; +	HEADER *hp = (HEADER *) answer; +	struct zonegrp *zptr = NULL, *tmpzptr, *prevzptr, *zgrp_start = NULL; +	int i, j, k = 0, n, ancount, nscount, arcount, rcode, rdatasize, +	    newgroup, done, myzone, seen_before, numzones = 0; +	u_int16_t dlen, class, qclass, type, qtype; +	u_int32_t ttl; + +	if ((_res.options & RES_INIT) == 0 && res_init() == -1) { +		h_errno = NETDB_INTERNAL; +		return (-1); +	} + +	for (rrecp = rrecp_in; rrecp; rrecp = rrecp->r_next) { +		dname = rrecp->r_dname; +		n = strlen(dname); +		if (dname[n-1] == '.') +			dname[n-1] = '\0'; +		qtype = T_SOA; +		qclass = rrecp->r_class; +		done = 0; +		seen_before = 0; + +		while (!done && dname) { +		    if (qtype == T_SOA) { +			for (tmpzptr = zgrp_start; +			     tmpzptr && !seen_before; +			     tmpzptr = tmpzptr->z_next) { +				if (strcasecmp(dname, +					       tmpzptr->z_origin) == 0 && +				    tmpzptr->z_class == qclass) +					seen_before++; +				for (tmprrecp = tmpzptr->z_rr; +				     tmprrecp && !seen_before; +				     tmprrecp = tmprrecp->r_grpnext) +				if (strcasecmp(dname, tmprrecp->r_dname) == 0 +				    && tmprrecp->r_class == qclass) { +					seen_before++; +					break; +				} +				if (seen_before) { +					/* +					 * Append to the end of +					 * current group. +					 */ +					for (tmprrecp = tmpzptr->z_rr; +					     tmprrecp->r_grpnext; +					     tmprrecp = tmprrecp->r_grpnext) +						(void)NULL; +					tmprrecp->r_grpnext = rrecp; +					rrecp->r_grpnext = NULL; +					done = 1; +					break; +				} +			} +		} else if (qtype == T_A) { +		    for (tmpzptr = zgrp_start; +			 tmpzptr && !done; +			 tmpzptr = tmpzptr->z_next) +			    for (i = 0; i < tmpzptr->z_nscount; i++) +				if (tmpzptr->z_class == qclass && +				    strcasecmp(tmpzptr->z_ns[i].nsname, +					       dname) == 0 && +				    tmpzptr->z_ns[i].nsaddr1.s_addr != 0) { +					zptr->z_ns[k].nsaddr1.s_addr = +					 tmpzptr->z_ns[i].nsaddr1.s_addr; +					done = 1; +					break; +				} +		} +		if (done) +		    break; +		n = res_mkquery(QUERY, dname, qclass, qtype, NULL, +				0, NULL, buf, sizeof buf); +		if (n <= 0) { +		    fprintf(stderr, "res_update: mkquery failed\n"); +		    return (n); +		} +		n = res_send(buf, n, answer, sizeof answer); +		if (n < 0) { +		    fprintf(stderr, "res_update: send error for %s\n", +			    rrecp->r_dname); +		    return (n); +		} +		if (n < HFIXEDSZ) +			return (-1); +		ancount = ntohs(hp->ancount); +		nscount = ntohs(hp->nscount); +		arcount = ntohs(hp->arcount); +		rcode = hp->rcode; +		cp = answer + HFIXEDSZ; +		eom = answer + n; +		/* skip the question section */ +		n = dn_skipname(cp, eom); +		if (n < 0 || cp + n + 2 * INT16SZ > eom) +			return (-1); +		cp += n + 2 * INT16SZ; + +		if (qtype == T_SOA) { +		    if (ancount == 0 && nscount == 0 && arcount == 0) { +			/* +			 * if (rcode == NOERROR) then the dname exists but +			 * has no soa record associated with it. +			 * if (rcode == NXDOMAIN) then the dname does not +			 * exist and the server is replying out of NCACHE. +			 * in either case, proceed with the next try +			 */ +			dname = strchr(dname, '.'); +			if (dname != NULL) +				dname++; +			continue; +		    } else if ((rcode == NOERROR || rcode == NXDOMAIN) && +			       ancount == 0 && +			       nscount == 1 && arcount == 0) { +			/* +			 * name/data does not exist, soa record supplied in the +			 * authority section +			 */ +			/* authority section must contain the soa record */ +			if ((n = dn_expand(answer, eom, cp, zname, +					sizeof zname)) < 0) +			    return (n); +			cp += n; +			if (cp + 2 * INT16SZ > eom) +				return (-1); +			GETSHORT(type, cp); +			GETSHORT(class, cp); +			if (type != T_SOA || class != qclass) { +			    fprintf(stderr, "unknown answer\n"); +			    return (-1); +			} +			myzone = 0; +			svdname = dname; +			while (dname) +			    if (strcasecmp(dname, zname) == 0) { +				myzone = 1; +				break; +			    } else if ((dname = strchr(dname, '.')) != NULL) +				dname++; +			if (!myzone) { +			    dname = strchr(svdname, '.'); +			    if (dname != NULL) +				dname++; +			    continue; +			} +			nscount = 0; +			/* fallthrough */ +		    } else if (rcode == NOERROR && ancount == 1) { +			/* +			 * found the zone name +			 * new servers will supply NS records for the zone +			 * in authority section and A records for those  +			 * nameservers in the additional section +			 * older servers have to be explicitly queried for +			 * NS records for the zone +			 */ +			/* answer section must contain the soa record */ +			if ((n = dn_expand(answer, eom, cp, zname, +			 	       	   sizeof zname)) < 0) +				return (n); +			else +				cp += n; +			if (cp + 2 * INT16SZ > eom) +				return (-1); +			GETSHORT(type, cp); +			GETSHORT(class, cp); +			if (type == T_CNAME) { +				dname = strchr(dname, '.'); +				if (dname != NULL) +					dname++; +				continue; +			} +			if (strcasecmp(dname, zname) != 0 || +			    type != T_SOA || +			    class != rrecp->r_class) { +				fprintf(stderr, "unknown answer\n"); +				return (-1); +			} +			/* FALLTHROUGH */ +		    } else { +			fprintf(stderr, +		"unknown response: ans=%d, auth=%d, add=%d, rcode=%d\n", +				ancount, nscount, arcount, hp->rcode); +			return (-1); +		    } +		    if (cp + INT32SZ + INT16SZ > eom) +			    return (-1); +		    /* continue processing the soa record */ +		    GETLONG(ttl, cp); +		    GETSHORT(dlen, cp); +		    if (cp + dlen > eom) +			    return (-1); +		    newgroup = 1; +		    zptr = zgrp_start; +		    prevzptr = NULL; +		    while (zptr) { +			if (strcasecmp(zname, zptr->z_origin) == 0 && +			    type == T_SOA && class == qclass) { +				newgroup = 0; +				break; +			} +			prevzptr = zptr; +			zptr = zptr->z_next; +		    } +		    if (!newgroup) { +			for (tmprrecp = zptr->z_rr; +			     tmprrecp->r_grpnext; +			     tmprrecp = tmprrecp->r_grpnext) +				    ; +			tmprrecp->r_grpnext = rrecp; +			rrecp->r_grpnext = NULL; +			done = 1; +			cp += dlen; +			break; +		    } else { +			if ((n = dn_expand(answer, eom, cp, primary, +				       	   sizeof primary)) < 0) +			    return (n); +			cp += n; +			/*  +			 * We don't have to bounds check here because the +			 * next use of 'cp' is in dn_expand(). +			 */ +			cp1 = (char *)soardata; +			strcpy(cp1, primary); +			cp1 += strlen(cp1) + 1; +			if ((n = dn_expand(answer, eom, cp, mailaddr, +				       	   sizeof mailaddr)) < 0) +			    return (n); +			cp += n; +			strcpy(cp1, mailaddr); +			cp1 += strlen(cp1) + 1; +			if (cp + 5*INT32SZ > eom) +				return (-1); +			memcpy(cp1, cp, 5*INT32SZ); +			cp += 5*INT32SZ; +			cp1 += 5*INT32SZ; +			rdatasize = (u_char *)cp1 - soardata; +			zptr = calloc(1, sizeof(struct zonegrp)); +			if (zptr == NULL) +                	    return (-1); +			if (zgrp_start == NULL) +			    zgrp_start = zptr; +			else +			    prevzptr->z_next = zptr; +			zptr->z_rr = rrecp; +			rrecp->r_grpnext = NULL; +			strcpy(zptr->z_origin, zname); +			zptr->z_class = class; +			memcpy(zptr->z_soardata, soardata, rdatasize); +			/* fallthrough to process NS and A records */ +		    } +		} else if (qtype == T_NS) { +		    if (rcode == NOERROR && ancount > 0) { +			strcpy(zname, dname); +			for (zptr = zgrp_start; zptr; zptr = zptr->z_next) { +			    if (strcasecmp(zname, zptr->z_origin) == 0) +				break; +			} +			if (zptr == NULL) +			    /* should not happen */ +			    return (-1); +			if (nscount > 0) { +			    /* +			     * answer and authority sections contain +			     * the same information, skip answer section +			     */ +			    for (j = 0; j < ancount; j++) { +				n = dn_skipname(cp, eom); +				if (n < 0) +					return (-1); +				n += 2*INT16SZ + INT32SZ; +				if (cp + n + INT16SZ > eom) +					return (-1); +				cp += n; +				GETSHORT(dlen, cp); +				cp += dlen; +			    } +			} else +			    nscount = ancount; +			/* fallthrough to process NS and A records */ +		    } else { +			fprintf(stderr, "cannot determine nameservers for %s:\ +ans=%d, auth=%d, add=%d, rcode=%d\n", +				dname, ancount, nscount, arcount, hp->rcode); +			return (-1); +		    } +		} else if (qtype == T_A) { +		    if (rcode == NOERROR && ancount > 0) { +			arcount = ancount; +			ancount = nscount = 0; +			/* fallthrough to process A records */ +		    } else { +			fprintf(stderr, "cannot determine address for %s:\ +ans=%d, auth=%d, add=%d, rcode=%d\n", +				dname, ancount, nscount, arcount, hp->rcode); +			return (-1); +		    } +		} +		/* process NS records for the zone */ +		j = 0; +		for (i = 0; i < nscount; i++) { +		    if ((n = dn_expand(answer, eom, cp, name, +					sizeof name)) < 0) +			return (n); +		    cp += n; +		    if (cp + 3 * INT16SZ + INT32SZ > eom) +			    return (-1); +		    GETSHORT(type, cp); +		    GETSHORT(class, cp); +		    GETLONG(ttl, cp); +		    GETSHORT(dlen, cp); +		    if (cp + dlen > eom) +			return (-1); +		    if (strcasecmp(name, zname) == 0 && +			type == T_NS && class == qclass) { +				if ((n = dn_expand(answer, eom, cp, +						   name, sizeof name)) < 0) +					return (n); +			    target = zptr->z_ns[j++].nsname; +			    strcpy(target, name); +		    } +		    cp += dlen; +		} +		if (zptr->z_nscount == 0) +		    zptr->z_nscount = j; +		/* get addresses for the nameservers */ +		for (i = 0; i < arcount; i++) { +		    if ((n = dn_expand(answer, eom, cp, name, +					sizeof name)) < 0) +			return (n); +		    cp += n; +		    if (cp + 3 * INT16SZ + INT32SZ > eom) +			return (-1); +		    GETSHORT(type, cp); +		    GETSHORT(class, cp); +		    GETLONG(ttl, cp); +		    GETSHORT(dlen, cp); +		    if (cp + dlen > eom) +			    return (-1); +		    if (type == T_A && dlen == INT32SZ && class == qclass) { +			for (j = 0; j < zptr->z_nscount; j++) +			    if (strcasecmp(name, zptr->z_ns[j].nsname) == 0) { +				memcpy(&zptr->z_ns[j].nsaddr1.s_addr, cp, +				       INT32SZ); +				break; +			    } +		    } +		    cp += dlen; +		} +		if (zptr->z_nscount == 0) { +		    dname = zname; +		    qtype = T_NS; +		    continue; +		} +		done = 1; +		for (k = 0; k < zptr->z_nscount; k++) +		    if (zptr->z_ns[k].nsaddr1.s_addr == 0) { +			done = 0; +			dname = zptr->z_ns[k].nsname; +			qtype = T_A; +		    } + + 	    } /* while */ +	} + +	_res.options |= RES_DEBUG; +	for (zptr = zgrp_start; zptr; zptr = zptr->z_next) { + +		/* append zone section */ +		rrecp = res_mkupdrec(ns_s_zn, zptr->z_origin, +				     zptr->z_class, ns_t_soa, 0); +		if (rrecp == NULL) { +			fprintf(stderr, "saverrec error\n"); +			fflush(stderr); +			return (-1); +		} +		rrecp->r_grpnext = zptr->z_rr; +		zptr->z_rr = rrecp; + +		n = res_mkupdate(zptr->z_rr, packet, sizeof packet); +		if (n < 0) { +			fprintf(stderr, "res_mkupdate error\n"); +			fflush(stderr); +			return (-1); +		} else +			fprintf(stdout, "res_mkupdate: packet size = %d\n", n); + +		/* +		 * Override the list of NS records from res_init() with +		 * the authoritative nameservers for the zone being updated. +		 * Sort primary to be the first in the list of nameservers. +		 */ +		for (i = 0; i < zptr->z_nscount; i++) { +			if (strcasecmp(zptr->z_ns[i].nsname, +				       zptr->z_soardata) == 0) { +				struct in_addr tmpaddr; + +				if (i != 0) { +					strcpy(zptr->z_ns[i].nsname, +					       zptr->z_ns[0].nsname); +					strcpy(zptr->z_ns[0].nsname, +					       zptr->z_soardata); +					tmpaddr = zptr->z_ns[i].nsaddr1; +					zptr->z_ns[i].nsaddr1 = +						zptr->z_ns[0].nsaddr1; +					zptr->z_ns[0].nsaddr1 = tmpaddr; +				} +				break; +			} +		} +		for (i = 0; i < MAXNS; i++) { +			_res.nsaddr_list[i].sin_addr = zptr->z_ns[i].nsaddr1; +			_res.nsaddr_list[i].sin_family = AF_INET; +			_res.nsaddr_list[i].sin_port = htons(NAMESERVER_PORT); +		} +		_res.nscount = (zptr->z_nscount < MAXNS) ?  +					zptr->z_nscount : MAXNS; +		n = res_send(packet, n, answer, sizeof(answer)); +		if (n < 0) { +			fprintf(stderr, "res_send: send error, n=%d\n", n); +			break; +		} else +			numzones++; +	} + +	/* free malloc'ed memory */ +	while(zgrp_start) { +		zptr = zgrp_start; +		zgrp_start = zgrp_start->z_next; +		res_freeupdrec(zptr->z_rr);  /* Zone section we allocated. */ +		free((char *)zptr); +	} + +	return (numzones); +}  | 
